This repository was archived by the owner on Oct 12, 2022. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 411
fix Issue 14439 - aa's keys, values, byKey, byValue not usable in @sa… #1644
Closed
Closed
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1923,12 +1923,13 @@ class __cpp_type_info_ptr | |
| extern (C) | ||
| { | ||
| // from druntime/src/rt/aaA.d | ||
| private: | ||
|
|
||
| // size_t _aaLen(in void* p) pure nothrow @nogc; | ||
| private void* _aaGetY(void** paa, const TypeInfo_AssociativeArray ti, in size_t valuesize, in void* pkey) pure nothrow; | ||
| void* _aaGetY(void** paa, const TypeInfo_AssociativeArray ti, in size_t valuesize, in void* pkey) pure nothrow; | ||
| // inout(void)* _aaGetRvalueX(inout void* p, in TypeInfo keyti, in size_t valuesize, in void* pkey); | ||
| inout(void)[] _aaValues(inout void* p, in size_t keysize, in size_t valuesize, const TypeInfo tiValArray) pure nothrow; | ||
| inout(void)[] _aaKeys(inout void* p, in size_t keysize, const TypeInfo tiKeyArray) pure nothrow; | ||
| inout(void)[] _aaValues(inout void* p, in size_t keysize, in size_t valuesize, const TypeInfo tiValArray) pure nothrow @trusted; | ||
| inout(void)[] _aaKeys(inout void* p, in size_t keysize, const TypeInfo tiKeyArray) pure nothrow @trusted; | ||
| void* _aaRehash(void** pp, in TypeInfo keyti) pure nothrow; | ||
| void _aaClear(void* p) pure nothrow; | ||
|
|
||
|
|
@@ -1938,7 +1939,13 @@ extern (C) | |
| // alias _dg2_t = extern(D) int delegate(void*, void*); | ||
| // int _aaApply2(void* aa, size_t keysize, _dg2_t dg); | ||
|
|
||
| private struct AARange { void* impl; size_t idx; } | ||
| struct AARange | ||
| { | ||
| private: | ||
| this(void *impl) { this.impl = impl; } | ||
| void* impl; | ||
| size_t idx; | ||
| } | ||
| AARange _aaRange(void* aa) pure nothrow @nogc; | ||
| bool _aaRangeEmpty(AARange r) pure nothrow @nogc; | ||
| void* _aaRangeFrontKey(AARange r) pure nothrow @nogc; | ||
|
|
@@ -2039,21 +2046,22 @@ V[K] dup(T : V[K], K, V)(T* aa) | |
| return (*aa).dup; | ||
| } | ||
|
|
||
| auto byKey(T : V[K], K, V)(T aa) pure nothrow @nogc | ||
| auto byKey(T : V[K], K, V)(T aa) pure nothrow @nogc @trusted | ||
| { | ||
| import core.internal.traits : substInout; | ||
|
|
||
| static struct Result | ||
| { | ||
| AARange r; | ||
|
|
||
| pure nothrow @nogc: | ||
| pure nothrow @nogc @trusted: | ||
| @property bool empty() { return _aaRangeEmpty(r); } | ||
| @property ref front() { return *cast(substInout!K*)_aaRangeFrontKey(r); } | ||
| void popFront() { _aaRangePopFront(r); } | ||
| @property ref front() { assert(!empty); return *cast(substInout!K*)_aaRangeFrontKey(r); } | ||
| void popFront() { assert(!empty); _aaRangePopFront(r); } | ||
| @property Result save() { return this; } | ||
| } | ||
|
|
||
| static assert(!__traits(compiles, __traits(getAliasThis, T)), "cannot have alias this of associative array"); | ||
| return Result(_aaRange(cast(void*)aa)); | ||
| } | ||
|
|
||
|
|
@@ -2062,21 +2070,22 @@ auto byKey(T : V[K], K, V)(T* aa) pure nothrow @nogc | |
| return (*aa).byKey(); | ||
| } | ||
|
|
||
| auto byValue(T : V[K], K, V)(T aa) pure nothrow @nogc | ||
| auto byValue(T : V[K], K, V)(T aa) pure nothrow @nogc @trusted | ||
| { | ||
| import core.internal.traits : substInout; | ||
|
|
||
| static struct Result | ||
| { | ||
| AARange r; | ||
|
|
||
| pure nothrow @nogc: | ||
| pure nothrow @nogc @trusted: | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. int main() @safe {
auto a = ["foo": 1];
auto r = a.byValue;
r.popFront;
return r.front; // oops
}
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To be fair, this is also applies to
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed |
||
| @property bool empty() { return _aaRangeEmpty(r); } | ||
| @property ref front() { return *cast(substInout!V*)_aaRangeFrontValue(r); } | ||
| void popFront() { _aaRangePopFront(r); } | ||
| @property ref front() { assert(!empty); return *cast(substInout!V*)_aaRangeFrontValue(r); } | ||
| void popFront() { assert(!empty); _aaRangePopFront(r); } | ||
| @property Result save() { return this; } | ||
| } | ||
|
|
||
| static assert(!__traits(compiles, __traits(getAliasThis, T)), "cannot have alias this of associative array"); | ||
| return Result(_aaRange(cast(void*)aa)); | ||
| } | ||
|
|
||
|
|
@@ -2085,15 +2094,15 @@ auto byValue(T : V[K], K, V)(T* aa) pure nothrow @nogc | |
| return (*aa).byValue(); | ||
| } | ||
|
|
||
| auto byKeyValue(T : V[K], K, V)(T aa) pure nothrow @nogc | ||
| auto byKeyValue(T : V[K], K, V)(T aa) pure nothrow @nogc @trusted | ||
| { | ||
| import core.internal.traits : substInout; | ||
|
|
||
| static struct Result | ||
| { | ||
| AARange r; | ||
|
|
||
| pure nothrow @nogc: | ||
| pure nothrow @nogc @trusted: | ||
| @property bool empty() { return _aaRangeEmpty(r); } | ||
| @property auto front() @trusted | ||
| { | ||
|
|
@@ -2114,6 +2123,7 @@ auto byKeyValue(T : V[K], K, V)(T aa) pure nothrow @nogc | |
| @property Result save() { return this; } | ||
| } | ||
|
|
||
| static assert(!__traits(compiles, __traits(getAliasThis, T)), "cannot have alias this of associative array"); | ||
| return Result(_aaRange(cast(void*)aa)); | ||
| } | ||
|
|
||
|
|
@@ -2124,8 +2134,15 @@ auto byKeyValue(T : V[K], K, V)(T* aa) pure nothrow @nogc | |
|
|
||
| Key[] keys(T : Value[Key], Value, Key)(T aa) @property | ||
| { | ||
| auto a = cast(void[])_aaKeys(cast(inout(void)*)aa, Key.sizeof, typeid(Key[])); | ||
| auto res = *cast(Key[]*)&a; | ||
| static assert(!__traits(compiles, __traits(getAliasThis, T)), "cannot have alias this of associative array"); | ||
| void* trustedCastVoid(T aa) @trusted { return cast(void*)aa; } | ||
| void* p = trustedCastVoid(aa); | ||
|
|
||
| void[] a = _aaKeys(p, Key.sizeof, typeid(Key[])); | ||
|
|
||
| Key[] trustedCastKeyArray(ref void[] a) @trusted { return *cast(Key[]*)&a; } | ||
| auto res = trustedCastKeyArray(a); | ||
|
|
||
| _doPostblit(res); | ||
| return res; | ||
| } | ||
|
|
@@ -2137,8 +2154,15 @@ Key[] keys(T : Value[Key], Value, Key)(T *aa) @property | |
|
|
||
| Value[] values(T : Value[Key], Value, Key)(T aa) @property | ||
| { | ||
| auto a = cast(void[])_aaValues(cast(inout(void)*)aa, Key.sizeof, Value.sizeof, typeid(Value[])); | ||
| auto res = *cast(Value[]*)&a; | ||
| static assert(!__traits(compiles, __traits(getAliasThis, T)), "cannot have alias this of associative array"); | ||
| void* trustedCastVoid(T aa) @trusted { return cast(void*)aa; } | ||
| void* p = trustedCastVoid(aa); | ||
|
|
||
| auto a = _aaValues(p, Key.sizeof, Value.sizeof, typeid(Value[])); | ||
|
|
||
| Value[] trustedCastValueArray(ref void[] a) @trusted { return *cast(Value[]*)&a; } | ||
| auto res = trustedCastValueArray(a); | ||
|
|
||
| _doPostblit(res); | ||
| return res; | ||
| } | ||
|
|
@@ -2175,6 +2199,20 @@ unittest | |
| assert(T.count == 2); | ||
| } | ||
|
|
||
| @safe unittest | ||
| { | ||
| string[string] saa = ["a" : "1", "b" : "2"]; | ||
| string s = saa["a"]; | ||
| saa["c"] = "3"; | ||
| if ("c" in saa) {} | ||
| size_t l = saa.length; | ||
| foreach(k; saa.keys) {} | ||
| foreach(k; saa.byKey) {} | ||
| foreach(v; saa.values) {} | ||
| foreach(v; saa.byValue) {} | ||
| foreach(k, v; saa) {} | ||
| } | ||
|
|
||
| inout(V) get(K, V)(inout(V[K]) aa, K key, lazy inout(V) defaultValue) | ||
| { | ||
| auto p = key in aa; | ||
|
|
@@ -2480,6 +2518,21 @@ unittest | |
| static assert(is(typeof(caa.byValue().front) == const int)); | ||
| } | ||
|
|
||
| unittest | ||
| { | ||
| static struct Foo { | ||
| int[int] aa; | ||
| auto opCast() pure nothrow @nogc { *cast(uint*)0xdeadbeef = 0xcafebabe; return null; } | ||
| alias aa this; | ||
| } | ||
|
|
||
| static void test() @safe { | ||
| Foo f; | ||
| static assert(!__traits(compiles, { int i = !f.byKey.empty; })); | ||
| } | ||
| } | ||
|
|
||
|
|
||
| private void _destructRecurse(S)(ref S s) | ||
| if (is(S == struct)) | ||
| { | ||
|
|
||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
Seeing
@trustedfollowed by:makes me nervous... IMO it's better to add it to each function signature individually.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.
I agree; besides the safety issue, I have run into over applied attribute issues in other PRs.
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.
Given that the functions it applies to are all right there and one liners, this isn't an issue, and implementing it would add clutter.
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.
But that's
-boundscheck=off's fault. It flat-out breaks@safe. An@safe/@trustedfunction may be unsafe with the switch, but it must be safe without it.