[Proposal]: Label statements #9124
Replies: 16 comments
-
Personally, I don't see the advantages over always putting a semicolon. Yes, it looks a little strange, but I don't really see that as an issue needing to be resolved. Could you clarify more what the debugging behavior you're seeing is? Maybe that can be resolved on its own in Roslyn without having to make a language change. |
Beta Was this translation helpful? Give feedback.
-
Avoiding looking strange is an advantage. It may not be hugely compelling, but it's an advantage nonetheless ;-)
The semicolon is its own statement. So you need to step through it. The additional advantage is someone needs to learn the workaround, after being bitten by it in the first place. I had to go and find all the places this was possibly happening and update them to include semicolons, which is not a natural instinct. |
Beta Was this translation helpful? Give feedback.
-
This is one of the few cases where since
That's probably a debugger improvement, probably an item for Visual Studio?
How can it be happening elsewhere, if the code doesn't compile without the semicolon? Or do you mean that you had actually added some "no-op" line as your previous workaround? |
Beta Was this translation helpful? Give feedback.
-
Source generators can have many different paths they take to output the source, in many combinations. It can take the right (wrong) sequence of events to end up with a label at the end of scope, in which case it fails to compile, but you don't discover it until you get that exact right sequence that leads to the label being not followed by another statement.
I expect it'll be used more commonly in source generators. In particular for source generators used to implement DSLs.
Again, the reason I raised source generators as the primary case for this is because they end up generating code that a human may not think to write. |
Beta Was this translation helpful? Give feedback.
-
Isn't this also code that a human is less likely to have to read? If the author of a source generator is concerned about how their code looks and can be parsed by a human I would think that the issue of following a label with an empty statement would be the least of their concerns. |
Beta Was this translation helpful? Give feedback.
-
"have to read", sure. But it's code being emitted into the project. It's part of the app. You debug through it just as you debug through code you wrote by hand. Source generator authors are (or at least, in my opinion, should be) concerned about making that code as nice to read and understand and debug as possible.
It is a concern. I've never said it's the most important thing in the world. I'm raising a real issue I've hit and that has a strange-looking workaround I had to discover and fix multiple times only after tripping over it multiple times. |
Beta Was this translation helpful? Give feedback.
-
Sure, I guess my point is that if you were optimizing for human readability of that generated code you very likely wouldn't be reaching for a label to begin with, especially not at the end of a block. This situation arises specifically because the code is generated and is already very unlike what a human would write manually. I'm not arguing against this proposal specifically, but I do think that it is kinda opening a can of worms to consider that the language syntax should be changed to reduce friction specifically for source generators. |
Beta Was this translation helpful? Give feedback.
-
The situation arises because it needs a branching structure that can't be represented well with if/elses, loops, etc. Sometimes gotos are actually the cleanest / most readable answer. |
Beta Was this translation helpful? Give feedback.
-
I'm not arguing against the use of |
Beta Was this translation helpful? Give feedback.
-
One thing I think is worth pointing out is that this feature does not complicate the language. It removes a wrinkle (I can't put a label at the end? I need an empty statement? What's an empty statement?) and as far as I can see smoothly generalizes the syntax. So I think the language would be the better for it. The main question then is, is it worth our effort? As has been pointed out above, use of There's a difference between a feature that is for source generation versus one that is motivated by it. If source generator scenarios are what can cause a small language clean-up to rise above the value threshold to invest in it then I have no problem with that. One thing that should be considered part of the cost of this feature is that it will change the shape of syntax trees for all existing uses of labels. Instead of being one Either way it seems to me to be a balancing of one-time cost vs long-term value. There does not seem to me to be ongoing cost (to the language, the compiler codebase or downstream tools) associated with this feature. |
Beta Was this translation helpful? Give feedback.
-
@HaloFour I don't think a label appearing at the end of a block is more special or unlikely than appearing at all. if (...)
{
for (...)
{
for (...)
{
if (...) goto afterBothLoops;
// ...
}
}
// There just happens to be nothing to do between the outer loop and the end of the scope containing it
afterBothLoops:
} If |
Beta Was this translation helpful? Give feedback.
-
It doesn't have to. We could represent this as a labeled statement with a true 'empty' child statement. This could be a new node type, or reusing the ';' statement (with a missing token), or just allowing the child to be optional here. That would keep the shape for all existing labels, but only as a new shape to understand for this new case. |
Beta Was this translation helpful? Give feedback.
-
Clever! It would not be the most natural representation but that might well be worth it for the back compat. |
Beta Was this translation helpful? Give feedback.
-
Right. Note, we often take the most 'compatible' representation, often with an eye toward 'ease of consumption' for the compiler model. For example, 'file scoped namespaces' are represented in a way such that the items that follow it in the file are actually represented as children of it (in the same fashion as normal namespaces). This allows high potential for continued reuse of the current shape, with little need to special case. |
Beta Was this translation helpful? Give feedback.
-
And the solution is to add yet another statement (that you'd have to step through)? |
Beta Was this translation helpful? Give feedback.
-
You already step through it. If I have: A();
Label:;
B(); and I'm on A(), I press F10 to take me to Label, then F10 to take me to the semicolon, then F10 to take me to B(). And if I have: A();
Label:
B(); and I'm on A(), I press F10 to take me to Label, then F10 to take me to B(). From a stepping perspective, Label is already a statement. |
Beta Was this translation helpful? Give feedback.
-
Label statements
Champion issue: #9125
Summary
Labels currently need to be part of statements but can't be statements on their own. We should consider making "Label:" a statement on its own.
Motivation
Source generators that utilize gotos and labels need to be aware when generating code whether a label being jumped to is at the end of a scope. If it is, emitting "Label:" will cause compilation failures, because the C# spec/compiler currently prohibit a label from being followed by a closing brace. e.g. if code is being generated for the equivalent of:
as:
the source generator now needs to either know that there will be additional code being generated after
AfterWork:
, track it to be able to output a semicolon if there isn't, or just always emit it as:which looks weird and makes for somewhat strange stepping behavior when debugging through the source-generated code. This is all because if it's emitted as:
that will fail to compile.
Detailed design
The C# specification currently states:
such that
Label:
is only permitted as part of "labeled statement", i.e. there has to be a statement to put the label on. We should consider allowingLabel:
to be a statement of its own.Drawbacks
Alternatives
Unresolved questions
Design meetings
Beta Was this translation helpful? Give feedback.
All reactions