-
-
Notifications
You must be signed in to change notification settings - Fork 706
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix Issue 17153 – Make std.container.array @nogc #5036
Conversation
|
@andralex requesting your review because this is a breaking change. |
std/container/array.d
Outdated
| @@ -142,26 +142,26 @@ private struct RangeT(A) | |||
|
|
|||
| E moveFront() | |||
| { | |||
| version (assert) if (empty || _a >= _outer.length) throw new RangeError(); | |||
| assert(!empty || _a < _outer.length); | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unless I'm having a dumb moment, this should use &&. !(foo || bar) = !foo && !bar. Same mistake throughout.
6e84f15 to
95d6d89
Compare
|
@wilzbach The coverage report that DMD generates and the coverage that appears on codecov are different. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, but I am not sure how far @andralex is on his journey to make it possible to use exceptions in @nogc?
That looks pretty weird and I am not sure how to fix this. Maybe @stevepeak (from CodeCov) knows the reason for this issue with CodeCov? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some late review comments
| auto newPayload = | ||
| enforce(cast(T*) malloc(sz))[0 .. oldLength]; | ||
|
|
||
| auto newPayloadPtr = cast(T*) malloc(sz); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider using pureMalloc next time ;)
std/container/array.d
Outdated
| _outer[_b - 1] = value; | ||
| } | ||
| /// Ditto | ||
| T moveBack() | ||
| { | ||
| enforce(!empty); | ||
| assert(!empty, "Attempting to mpve the back of an empty Array"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
move typo
|
Hey @wilzbach can you check if the webhook is setup and sending to Codecov? Status was waiting on a webhook. Thank you! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, there's a fair amount of stuff to discuss here.
First, there are a few version(assert) things that throw a different exception. These are safe to commit. Yes, there is a technical breakage, but a palatable one.
Second, there are a few memory allocations that have been changed from enforce to assert. That makes them UB. We don't want that. It should be okay to finish the application upon allocation failure, but not UB.
Third, the bulk is a change in philosophy. Currently, calling front against an empty container caused an exception, so it was defined behavior. This PR makes it undefined. This is definitely not OK for backwards compatibility.
Instead, I propose to make a small PR with the noncontroversial changes in it.
Second, change the remaining instances of enforce with throwing a statically-allocated exception similar to dlang/druntime#1710. That way we'd technically break code (what if someone collects an array of exceptions?) but the scope would be smaller.
The saving grace of this is the documentation doesn't specify current behavior, so we're free to do as we please :). Please accompany this and the following PRs with appropriate documentation changes.
Thanks!
std/container/array.d
Outdated
| enforce(cast(T*) malloc(sz))[0 .. oldLength]; | ||
|
|
||
| auto newPayloadPtr = cast(T*) malloc(sz); | ||
| assert(newPayloadPtr, "std.container.Array.reserve failed to allocate memory"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's do this: newPayloadPtr || assert(false, "std.container.Array.reserve failed to allocate memory");
std/container/array.d
Outdated
| enforce(cast(T*) realloc(_payload.ptr, sz))[0 .. length]; | ||
| auto newPayloadPtr = cast(T*) realloc(_payload.ptr, sz); | ||
| assert(newPayloadPtr, "std.container.Array.reserve failed to allocate memory"); | ||
| auto newPayload = newPayloadPtr[0 .. length]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here, end the app if no memory.
std/container/array.d
Outdated
| @@ -547,7 +550,8 @@ Complexity: $(BIGOH 1) | |||
| bool overflow; | |||
| const sz = mulu(elements, T.sizeof, overflow); | |||
| if (overflow) assert(0); | |||
| auto p = enforce(malloc(sz)); | |||
| auto p = malloc(sz); | |||
| assert(p); | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here, end the app if no memory.
std/container/array.d
Outdated
| @@ -805,7 +809,7 @@ Complexity: $(BIGOH log(n)). | |||
| */ | |||
| void removeBack() | |||
| { | |||
| enforce(!empty); | |||
| assert(!empty); | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does not belong with this PR, it's a (breaking) change in philosophy.
std/container/array.d
Outdated
| @@ -855,7 +859,7 @@ Complexity: $(BIGOH n + m), where $(D m) is the length of $(D stuff) | |||
| if (isImplicitlyConvertible!(Stuff, T)) | |||
| { | |||
| import std.conv : emplace; | |||
| enforce(r._outer._data is _data && r._a <= length); | |||
| assert(r._outer._data is _data && r._a <= length); | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does not belong with this PR, it's a (breaking) change in philosophy.
std/container/array.d
Outdated
| return cast(bool)(data.back & (cast(size_t)1 << ((_store._length - 1) % bitsPerWord))); | ||
| } | ||
|
|
||
| /// Ditto | ||
| @property void back(bool value) | ||
| { | ||
| enforce(!empty); | ||
| assert(!empty); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does not belong with this PR, it's a (breaking) change in philosophy.
std/container/array.d
Outdated
| @@ -1767,15 +1788,15 @@ if (is(Unqual!T == bool)) | |||
| { | |||
| auto div = cast(size_t) (i / bitsPerWord); | |||
| auto rem = i % bitsPerWord; | |||
| enforce(div < data.length); | |||
| assert(div < data.length); | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does not belong with this PR, it's a (breaking) change in philosophy.
std/container/array.d
Outdated
| return cast(bool)(data.ptr[div] & (cast(size_t)1 << rem)); | ||
| } | ||
| /// ditto | ||
| void opIndexAssign(bool value, size_t i) | ||
| { | ||
| auto div = cast(size_t) (i / bitsPerWord); | ||
| auto rem = i % bitsPerWord; | ||
| enforce(div < data.length); | ||
| assert(div < data.length); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does not belong with this PR, it's a (breaking) change in philosophy.
std/container/array.d
Outdated
| @@ -1784,7 +1805,7 @@ if (is(Unqual!T == bool)) | |||
| { | |||
| auto div = cast(size_t) (i / bitsPerWord); | |||
| auto rem = i % bitsPerWord; | |||
| enforce(div < data.length); | |||
| assert(div < data.length); | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does not belong with this PR, it's a (breaking) change in philosophy.
std/container/array.d
Outdated
| @@ -2050,7 +2071,7 @@ if (is(Unqual!T == bool)) | |||
| */ | |||
| void removeBack() | |||
| { | |||
| enforce(_store._length); | |||
| assert(_store._length); | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does not belong with this PR, it's a (breaking) change in philosophy.
The problem is that we merge the upstream branch into the PR and thus generate slightly different |
b653798 to
5f5a444
Compare
|
@andralex Removed controversial changes |
5f5a444 to
ccff296
Compare
|
Auto-merge toggled on |
Despite
Arraynot using the GC for allocating its elements, it was still unusable for@nogccode because of its use ofthrowandenforce.This PR turns those into
assertsand makes the majority of the functions@nogc.