Fix Issue 19754 - Re-apply #9505 and fix it, making isLvalue() logic more restrictive wrt. literals#10124
Conversation
|
Thanks for your pull request and interest in making D better, @kinke! We are looking forward to reviewing it, and you should be hearing from a maintainer soon.
Please see CONTRIBUTING.md for more information. If you have addressed all reviews or aren't sure how to proceed, don't hesitate to ping us with a simple comment. Bugzilla references
|
| } | ||
|
|
||
| bool binOptimize(BinExp e, int flags) | ||
| bool binOptimize(BinExp e, int flags, bool keepLhsLvalue = false) |
There was a problem hiding this comment.
There are 14 other call sites in this file I'd rather not touch.
There was a problem hiding this comment.
Let's say it's okay since it's not a new func.
|
https://github.com/dlang/dmd/blob/master/test/fail_compilation/test6883.d doesn't fail anymore (compile-time bounds checks). |
|
In the 3rd commit, I tried to tentatively optimize the |
1faa809 to
5b6e828
Compare
|
After much trial and error, there seems to be light at the end of the tunnel. The Phobos unittest compile errors are due to some |
e7a3337 to
2423d88
Compare
src/dmd/expression.d
Outdated
| override bool isLvalue() | ||
| { | ||
| return true; | ||
| return e1.op != TOK.structLiteral; |
There was a problem hiding this comment.
The problem with structLiteral is not wether they are Lvalue or not it's rather that when they are they are not modifiable Lvalues.
test/fail_compilation/b20011.d
Outdated
| fail_compilation/b20011.d(31): Error: `U1(cast(ubyte)0u, ).m2` is not an lvalue and cannot be modified | ||
| fail_compilation/b20011.d(35): Error: function `b20011.main.assignableByRef(ref ubyte p)` is not callable using argument types `(ubyte)` | ||
| fail_compilation/b20011.d(35): cannot pass rvalue argument `S1(cast(ubyte)0u).member` of type `ubyte` to parameter `ref ubyte p` | ||
| fail_compilation/b20011.d(36): Error: function `b20011.main.assignableByOut(out ubyte p)` is not callable using argument types `(ubyte)` |
There was a problem hiding this comment.
The messages in my PR are better. Yours don't mention anything about constness and are rather confusing
There was a problem hiding this comment.
The test cases are in now. Free to you to rework but I still think that it's sub-accurate to just output that the func cant be called. The user would have to think more about the why.
Return false for fields of struct literals.
Which just patched over some cracks wrt. accessing fields of struct literals. Not a full revert, as the (useful) test cases are kept.
|
Rebased once more... |
|
This broke our code. Reduced test case: public T deserializeFull (T) () @safe
{
static if (is(T : E*, E))
{
return &[ deserializeFull!(typeof(T.init[0]))() ][0];
}
return T.init;
}
struct Block { string value; }
void main ()
{
auto b = deserializeFull!(immutable(Block)*)();
}Here, the literal is a GC allocation, so why is the compiler refusing it ? Moreover, I'm asking for an |
Thanks, can we have a regression issue? |
|
Sure. Just wanted to confirm if that was intended. Anyway, opened https://issues.dlang.org/show_bug.cgi?id=21312 |
It may be intended, but I think is better to digress in a bug report. |
|
This is intended. People seem to have abused this |
|
It might be nice to have a little extern (C) void* _d_newitemU(in TypeInfo _ti);
T* moveToGC(T)(auto ref T value)
{
import core.lifetime;
auto mem = cast(T*) _d_newitemU(typeid(T)); // allocate without initializing
moveEmplace(value, *mem);
return mem;
}
public T deserializeFull (T) () @safe
{
static if (is(T : immutable E*, E))
return () @trusted { return cast(T) deserializeFull!E.moveToGC(); }();
else
return T.init;
} |
|
Well I'd be happy to use |
|
I guess that would be fixable for array literals with at least one element, but I'd still consider |
"I consider this syntax obscure" is not reason enough to break the language. If it was, I would have nuked |
|
That comment was wrt. your code example, not in general. The benefit IMO is consistency. Indexing or dot-var'ing a literal now consistently yields an rvalue, array literals being no exception. My thinking was that a part of a literal is still a literal. E.g., this used to compile too (without struct S { int x; }
void main() { auto p = &S(0).x; *p = 123; }IIRC (it's been a while), NOT doing this would lead to compile errors with master not being caught by the compiler anymore after cast-related changes/fixes in earlier commits. |
As hopefully idiomatic alternative to the `&[value][0]` 'pattern', which doesn't compile anymore since dlang/dmd#10124.
As hopefully idiomatic alternative to the `&[value][0]` 'pattern', which doesn't compile anymore since dlang/dmd#10124.
As hopefully idiomatic alternative to the `&[value][0]` 'pattern', which doesn't compile anymore since dlang/dmd#10124.
I would rather have the compiler be consistent on the whole expression than just two levels of it.
Right, but const foo = [ 42, 24 ];If we want to be consistent, shouldn't this give us a And yeah, the code you liked is obviously wrong, and I'm glad you put so much effort into fixing this. I just think we can do this fix while still retaining the old behavior when someone takes the address of an array literal. |
|
I gave this some more thought yesterday. I do see that a (dynamic) array literal is a special case, and while the slice itself is an rvalue, its elements clearly are not. On the other hand, emplacing a single element in a new GC-allocation is the only use case I can think of for immediately indexing an array literal, and that comes with associated array overhead (it will never be appended to, as there's no reference to the array literal anymore when immediately indexing it). So I think I can open a new PR treating array literal elements as lvalues again, to check the effect on the compile errors. |
As hopefully idiomatic alternative to the `&[value][0]` 'pattern', which doesn't compile anymore since dlang/dmd#10124.
As hopefully idiomatic alternative to the `&[value][0]` 'pattern', which doesn't compile anymore since dlang/dmd#10124.
As hopefully idiomatic alternative to the `&[value][0]` 'pattern', which doesn't compile anymore since dlang/dmd#10124.
As hopefully idiomatic alternative to the `&[value][0]` 'pattern', which doesn't compile anymore since dlang/dmd#10124.
|
This introduced regression https://issues.dlang.org/show_bug.cgi?id=23273 |
These issues have surfaced with #9505 (mainly with non-DMD backends).