-
-
Notifications
You must be signed in to change notification settings - Fork 614
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
cast(ref T)...
as shorthand for *cast(T*)&...
#20644
Comments
I think re-interpret casting is ugly by design. |
We'll it's obviously a @safe violation... so it's not :P |
Imagine code looking something like this: import std.bitmanip;
void main()
{
read!ushort(cast(ubyte[]) [0xAA, 0xBC, 0xDE]);
} Which then gets changed to: - read!ushort(cast(ubyte[]) [0xAA, 0xBC, 0xDE]);
+ read!ushort(cast(ref ubyte[]) [0xAA, 0xBC, 0xDE]); Is it obvious we're doing a re-interpret cast of an int[] suddenly? To me, it looks like it promotes the rvalue to an lvalue. You have to specifically know the meaning we gave to - read!ushort(cast(ubyte[]) [0xAA, 0xBC, 0xDE]);
+ read!ushort(*cast(ubyte[]*) &[0xAA, 0xBC, 0xDE]);
As they shouldn't, but nice-looking syntax makes it much easier to do accidentally or haphazardly. |
Ummm, no that's not what this is about. Infact, this is invalid in the case you show.
I'm not sure what you're trying to demonstrate here, it just looks invalid to me.
This is invalid code, and so the shorthand I proposed is equally invalid for the same reason; you can't cast an rvalue to an lvalue.
Aside from the conceptual errors above, which makes me suspect you might not have understood what it is I'm proposing, or why, but generally I don't buy into this point either... I firmly think writing It has nothing to do with making it 'nice-looking', it's about making a complex and difficult to reason about expression reasonable. The current situation with the |
I know that my example is not what you are trying to do. Let me clarify. I said "unsafe constructs should look unsafe" I attempted to illustrate this point by giving a hypothetical scenario of someone trying to pass an rvalue to a
My point is, it's not clear. Let me try a different angle: I gave this ChatGPT this promp:
And it answered:
And it gave this code example: int x = 10;
auto y = cast(ref int) x; // `y` is now a reference to `x`
y = 20; // Modifies `x` directly And that would also be my first impression of the syntax. But even if the proposed syntax was
He's been against all of these. However, if you go through with this, it's ultimately up to him and Atila to evaluate and decide. |
If you do this a lot, you can always define your own helper function. T reinterpret_cast(T, V)(V value) => *cast(T*)& value;
float x = reinterpret_cast!float(0x3F800000); I know I know, you don't want call instructions, and you don't want the debugger to step into trivial functions like that, but I'm starting to see a pattern here: perhaps we just need to make |
This is exactly correct! That's why I suggest that syntax, because it seems logical and self-evident.
The point where GPT failed is not noticing that |
I gotta admit that it's technically correct, but the focus is clearly on 'ensuring that the resulting value is treated as a reference' (which it fails to do in the code example) and not on re-interpret casting. When I ask about type mismatches, it says:
Of course I don't want to give too much weight to an LLM's opinion, but if the syntax was truly self-evident, there wouldn't even be a discussion here. It doesn't help that |
Maybe cast needs a do-over like C++ did 15 years ago... |
I agree. From the top of my head:
etc. |
As there's no opCast for a pointer, the original pattern is more flexible. See also #18852 which seems the same. As that says, the feature would allow some |
I'm not sure what you are saying here?
Nice to know that Andrei had the same thought. |
Consider:
I have a hard time finding something wrong with it. Looking at @dkorpel's reinterpret_cast, that has a weakness because it always returns an rvalue, and the In fact, Certainly, cast to ref should always be marked unsafe. I totally agree with @dkorpel saying that doing nasty things should look nasty. But every case should be evaluated on its individual merits. I admit I'm kinda seduced by this one. |
Absolutely.
Pretty sure any such thunk is unsafe.
Huzzah. I honestly didn't see that coming! |
That's easily fixed. I made my example with rvalues, but you can also make it work on both with -T reinterpret_cast(T, V)(V value) => *cast(T*) &value;
+ref T reinterpret_cast(T, V)(ref V value) => *cast(T*) &value; |
Oh don't say that, Walter's mildly persuaded. That never happens! |
They don't call me Dr No for nothing! |
@dkorpel ok |
this needs explicit definition (and a test case) of what I think the pattern is:
So that would mean: Therefore, I agree with Dennis that the chosen syntax |
You're quite right in that But that wouldn't make much sense anyway, as I can't think of a use for it that makes any sense. Or maybe my imagination is faulty :-/ I think of it differently, as in "refer to When Manu first proposed it, my first reaction was negative, too. But it grew on me. It makes D code nicer looking, and that is very much a goal of D. When I write expressions like It's ok if we overload the meaning of a keyword now and then. This use quickly becomes very natural. |
I disagree. This is not going to be something you see every day. I'm convinced most people will read the cast as casting to It shouldn't be too hard to come up with a better syntax. |
If the benefit to this syntax sugar was more than just saving a few keystrokes, I'd be more inclined to agree with this. |
This doesn't mitigate a few key strokes, it mitigates confusion and error. |
I'm not sure what you mean, that's EXACTLY what it does. I think the syntax couldn't be clearer or more precise.
It's perfect, no better syntax could possibly exist, it couldn't be more precisely expressing what it does. |
I'm not sure what you mean here, that's exactly what it says, and that's exactly what it should do.
No reason this expression shouldn't work just how it looks like it should. I don't think the meaning is overloaded in any way, I think it's precisely that it looks like it means. |
Now you just have to carefully count the number of asterisks and subtract one instead of adding one. |
Why would you subtract one? The |
That's exactly why you need to subtract one. If you dereference a |
Yeah no, I don't know how you're managing to overcomplicate this, but what you say just appears to demonstrates a deep misunderstanding of a thunk. No need to overcomplicate your conception of this, the most obvious and logical interpretation of the syntax is exactly what it should mean. |
Exactly what it means if you didn't type
This doesn't mitigate a few key strokes, it mitigates confusion and error. Sorry, I reread and I follow what you're saying now. You note that the traditional thunk adds an additional * to complement the defence. That's not necessary with this syntax; hence the "no need to add an extra *". You just handle the type your want, and no need to manipulate it. If may be an alias with no extra grammar required. |
It means:
is literally replaced with:
in the implementation. |
It explicitly means:
Nothing more, nothing less. It is a rewrite of the AST prior to semantic analysis. I.e. it is nothing more than syntactic sugar. No further test cases are needed. |
Yes, exactly this. I presume lvalue assignment is also possible, just as: |
Of course it works, because the AST for I mean literally literally. Look at the implementation! It's just 4 lines. Literally! Literally! |
Yes, exactly. It's perfect! |
It is of course of no use writing that in the PR. You have to put it in the spec. And test it.
the point is: test what |
If we want to make reinterpreting casts less confusing, it seems to me like the obvious way to do it is to add a pragma(inline, true)
ref T reinterpretCast(T, U)(ref U u)
{
return *cast(T*) &u;
} Both Keep in mind that we've had complaints in the past about "syntax churn" from maintainers of tooling projects, like libdparse and sdfmt. So even a purely-additive syntactic change like this one is not 100% free. |
https://github.com/dlang/dlang.org/pull/4164/files
https://github.com/dlang/dmd/pull/20728/files
Think of |
Isn't that true with about everything in a programming language? I look at other languages, and see plenty of unfamiliar constructs.
And I am sensitive to that. That's why I expended a fair amount of effort making the lexer and parser each be standalone modules, so other tools can incorporate it without needing to invent their own.
Indeed, that is always a difficult judgement call to make. A major goal of D is to make it pleasant to read (but not necessarily easier to type). When |
I agree that Also, if your objection is mainly to the name
|
Fine. The point still stands (unsurprisingly): nowhere do you test that |
What I'm most concerned about between this language change and the ones linked is that none of them are going through the DIP process. Perhaps not surprising, given that these proposals taking the direct route have gotten more useful feedback in just a few weeks than the entire new process has in nearly a year. They might even be accepted and implemented! You just can't get that level of attention from the DIP process, even right back when that was promised. |
The test is that the same results result. Frankly, none of the compiler tests test AST tree topology. If you would like to add a specific test, please describe it. |
|
Ironic that you mention that! The reason for the very existence of the |
I should have been more specific. I meant the normal DIP process, not the special Walter DIP process. The normal DIP process starts with posting a proposal on the DIP ideas forum and getting none of the promised feedback from you and/or Atila. It's been rather discouraging for us peasants. |
I don't understand, why do you think it's non-obvious? What would you imagine that's different from what it does? You could have:
I think everyone should understand what this does, and what seems most obvious to me, is that this syntax is exactly this same thing. |
@Herringway I have not proposed any of these ideas. They all came from others. Some took umbrage at being asked to write a DIP. Perhaps you or someone else could help them write the DIP? In the meantime, we have an implementation to try out the idea. |
Can we enhance cast expressions to do lvalue thunk's?
This classic pattern
*cast(T*)&...
; there's a lot of cognitive baggage going on there!We should be able to write
cast(ref T)...
instead.The text was updated successfully, but these errors were encountered: