[new AA] implement aaLiteral #933
[new AA] implement aaLiteral #933
Conversation
values ~= cast(Value)args[i+1]; | ||
} | ||
|
||
void[] key_slice = (cast(void*)keys.ptr)[0 .. keys.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.
Huh? What if Key.sizeof != (void*).sizeof
?
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.
This is void
slice, not void*
. And yes, Key.sizeof can be not equals with void.sizeof. However _d_assocarrayliteralTX
void[]
takes slice with length == keys count. See rt/aaA.d:562
:
Impl* _d_assocarrayliteralTX(const TypeInfo_AssociativeArray ti, void[] keys, void[] values)
{
...
const length = keys.length;
...
assert(length == values.length);
...
for (size_t j = 0; j < length; j++)
{ auto pkey = keys.ptr + j * keysize;
auto pvalue = values.ptr + j * valuesize;
...
}
...
}
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.
Oh yuck it's one of those APIs.
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.
Yes :)
This is another one reason to replace old AA implementation.
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'd rather you did it via *(cast(void[]*)&keys)
instead to make it clear it's a reinterpret cast.
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.
Done
8396e88
to
2c03e7a
Compare
Reworked. Now this PR introduce only aaLiteral, because my last AA implementation use zero AA init (similar old AA). |
@MartinNowak ping |
Is the dmd pull ready yet, or were you planning to merge this first and submit the dmd changes later? |
This PR should be merged first. After that, dmd pull should pass tests (they are passed on my machine). After dmd pull will be merged (of course, it should be reviewed first), I will create the next druntime PR. It will be simple and use AA implementation from #934 (which are also waitinig for review). |
OK, makes sense. I'll leave it to them to approve this PR then. |
void* _d_assocarrayliteralTX(const TypeInfo_AssociativeArray ti, void[] keys, void[] values) @trusted pure; | ||
} | ||
|
||
auto aaLiteral(Key, Value, T...)(T args) @trusted |
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.
Isn't @trusted a potential safety hole here if any of the argument types define a custom opCast?
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.
Current AA implementation is one big hole:
void* p;
struct MyKey
{
size_t a;
size_t toHash() const
{
p = cast(void*)a;
if (a == 5)
throw new Exception("hello");
return a;
}
}
void main() @safe pure nothrow
{
int[MyKey] aa;
aa[MyKey(3)] = 3;
aa[MyKey(5)] = 5; //BOOOM
}
This code succesfully compiles and runs on dmd v2.066
This PR is a transitional stage between current implementation and new good, safe template-based implementation.
This PR doesn't brings something new. Where dmd inserts aaLiteral
, it called _d_assocarrayliteralTX
without any checks early.
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.
Should this use auto ref T args
to avoid temporary copies?
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.
auto ref causes an unexpected troubles on some tests. May be it's a compiler bug, may be it is my bug in dmd code. If dlang/dmd#3904 will be reviewed by someone dmd guru like @9rnsr my possible bug can be found. But for review 3904 we need merge this code.
I think this is not big issue, because this code will be replaced with new AA fast enough (I hope until the next release).
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.
Done. I've fixed bug in my dmd patch. Now we can use auto ref arguments in aaLiteral.
Key[] keys; | ||
Value[] values; | ||
keys.reserve(T.length / 2); | ||
values.reserve(T.length / 2); |
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.
auto keys = new Key[](T.length / 2);
auto values = new Value[](T.length / 2);
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.
No. If I'll construct a array compiler will initialize it with init data (is Value is a struct with @disable this()
it causes a error).
After that I'll shoud to assign (call opAssign) instead of adding new values.
a36d857
to
ea68760
Compare
@MartinNowak I've applied changes that you asked, except setting array elements by index (I said why). |
@MartinNowak Please, rereview it. |
ea68760
to
87c1ca8
Compare
@MartinNowak ping |
@MartinNowak may be this PR can be merged? It is so trivial and its merging allows to start review of dmd part. And when you will able to review #934 PR? |
@MartinNowak ping |
foreach (i; staticIota!(0, args.length / 2)) | ||
{ | ||
keys ~= cast(Key)args[2*i]; | ||
values ~= cast(Value)args[2*i + 1]; |
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.
Casting could be unsafe here, so remove the @trusted
from above and let the compiler infer it.
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.
Hmm. I've removed casts and tests have been passed. I can't remember, why I added them. =/
I can't remove @trusted
, because void[] key_slice = *cast(void[]*)&keys;
is unsafe. (It's part of old AA API)
OK, let's get this going. I'm still not really happy with the template bloat caused the variadic template arguments, but we can optimize the details later. |
87c1ca8
to
acb4399
Compare
@MartinNowak is it ok now? |
@MartinNowak Please, if you see my changes but not ready to review this, tell me something like |
Well it isn't seen, because I only look at my github inbox when I have time. |
We still have to let the compiler infer safety because appending a struct to an array might call an unsafe postblit. void[] key_slice, value_slice;
() @trusted {
key_slice = *cast(void[]*)&keys;
value_slice = *cast(void[]*)&values;
}(); |
void* _d_assocarrayliteralTX(const TypeInfo_AssociativeArray ti, void[] keys, void[] values) @trusted pure; | ||
} | ||
|
||
auto aaLiteral(Key, Value, T...)(auto ref T args) @trusted |
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 add if (T.sizeof % 2 == 0)
as template constraint.
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.
done
acb4399
to
d236d1c
Compare
Pretty syntax. Done. |
7c37851
to
7c52734
Compare
@MartinNowak done. Also I've moved |
Yikes, I'm not even sure we can optimize away the function call. |
Oh, hadn't seen that before. Please also add all declared attributes to the implementation, it probably cannot be pure. |
It CAN be impure. And we can't check the purity.
Compiler doesn't provide any check and inserts |
In other words, we can't make |
Then please add a comment to the declaration explaining why it is marked as pure even though it isn't. |
7c52734
to
a213c6b
Compare
done |
Auto-merge toggled on |
Thanks a lot for driving this. |
Why |
Sorry, ignore my comment. |
Thanks! Now it's time to #934 |
[new AA] implement aaLiteral
We need to improve this even if it's only an interim interface. |
How your sugest to do it? Arguments passed in stack in rotation. We need to two separate slices.
If we will not linger, we will apply all parts of work and throw |
Indeed it's fairly difficult as long as the implementation sits in rt. So yes we need to defer this. |
This functions will be used to constructing AA values: literals and nulls. When this PR will be merged, I will create PR for dmd, which uses this functions, and when dmd PR will be merged, I'll create PR, which rewrite this functions to use new AA implementation.