Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upTracking issue for RFC 2046, label-break-value #48594
Comments
Centril
added
B-RFC-approved
T-lang
C-tracking-issue
labels
Feb 27, 2018
This comment has been minimized.
This comment has been minimized.
SoniEx2
commented
Feb 28, 2018
|
Using "return" would have interesting implications for labeled |
This comment has been minimized.
This comment has been minimized.
@mark-i-m and @joshtriplett have already spoken out against return, but I'll join in given that it is still apparently an unresolved question.
In C, C++, Java, C#, JavaScript and probably more languages you are usually The "rules to remember" argument works into the other direction really well however. From what I can tell it is a commonality of the mentioned languages as well as Rust that return only applies to functions and nothing else. So if you see a return, you know that a function is being left.
First, I think this happens very rarely as the labeled break feature is admittedly not something that will be used 10 times per 1000 lines. After all, it will only apply to unlabeled breaks that would cross the boundary of the block, not unlabeled breaks inside the block. Second, users of Rust are accustomed to complaints / error messages by the compiler, they will happily fix them! Third (this is the strongest point I think), if instead of labeling a block you wrap it into a loop, you already need to watch out for unlabeled breaks and there is no error message that conveniently lists the break statements, you've got to hunt for them yourself :). |
This comment has been minimized.
This comment has been minimized.
This to me is the killer point. break from blocks is a thing in many languages. return from blocks...not so much. |
This comment has been minimized.
This comment has been minimized.
|
Personally, I share @joshtriplett's view on using |
This comment has been minimized.
This comment has been minimized.
|
Just saying that I'm working on this. Don't need mentor instructions. Just to not duplicate any efforts. Expect a PR soon. |
This comment has been minimized.
This comment has been minimized.
|
I'm still in favour of |
bors
added a commit
that referenced
this issue
May 16, 2018
This comment has been minimized.
This comment has been minimized.
|
Currently (with |
This comment has been minimized.
This comment has been minimized.
|
@topecongiro Yes, I believe it's intentional that this is currently allowed only on plain blocks. It might change in future, but given that this is such a low-level and unusual feature, I'm inclined towards that being a feature rather than a restriction. (On the extreme, I certainly don't want |
This comment has been minimized.
This comment has been minimized.
|
Definitely agree. Unsafe + unusual control flow sounds like something to discourage. In a pinch, though, you could use: 'a: {
unsafe {...}
}Right? |
This comment has been minimized.
This comment has been minimized.
SoniEx2
commented
May 22, 2018
•
|
Actually, altho else does create a new lexical scope, it's not a block. The whole if-else is a block (kinda). So no, you wouldn't get |
This comment has been minimized.
This comment has been minimized.
|
|
This comment has been minimized.
This comment has been minimized.
That's a great observation! |
This comment has been minimized.
This comment has been minimized.
SoniEx2
commented
May 22, 2018
|
I think labels should be part of block-containing expressions, not blocks themselves. We already have precedent for this with (Things like |
This comment has been minimized.
This comment has been minimized.
Only if |
This comment has been minimized.
This comment has been minimized.
|
@mark-i-m It's equivalent to |
This comment has been minimized.
This comment has been minimized.
|
Woah, I find that highly unintuitive. I expect |
This comment has been minimized.
This comment has been minimized.
|
Oh |
This comment has been minimized.
This comment has been minimized.
|
This is why I don't like labeled break/continue :/ |
This comment has been minimized.
This comment has been minimized.
|
Well, we specifically don't have the ability to label these weird inner blocks, so I don't see the problem. |
This comment has been minimized.
This comment has been minimized.
|
My confusion was not specific to weird inner blocks, but I don't really want to reopen the discussion. That already happened and the community decided to add it. |
This comment has been minimized.
This comment has been minimized.
SoniEx2
commented
May 24, 2018
|
Okay, I understand accessibility is a big issue with programming languages... however, labeled break is extremely useful if you write code like me. So, how can we make labeled break more accessible? |
This comment has been minimized.
This comment has been minimized.
That's a great question. Some ideas I had:
As a first (admittedly biased) sample, my last (and first) encounter with labeled break in real code was not stellar: https://github.com/rust-lang/rust/pull/48456/files#diff-3ac60df36be32d72842bf5351fc2bb1dL51. I respectfully suggest that if the original author had put in slightly more effort they could have avoided using labeled break in that case altogether... This is an example of the sort of practice I would like to discourage if possible. |
This comment has been minimized.
This comment has been minimized.
|
That's... not labeled break? |
This comment has been minimized.
This comment has been minimized.
|
Regarding how |
This comment has been minimized.
This comment has been minimized.
|
If it matters at all: Zig also has this feature. |
This comment has been minimized.
This comment has been minimized.
|
On January 5, 2019 9:18:29 AM PST, Mazdak Farrokhzad ***@***.***> wrote:
@rfcbot resolve
give-boats-and-josh-time-to-raise-any-concerns-they-might-still-have
We've raised concerns already, and they amount to "this shouldn't be in the language". Those concerns aren't going away.
I prefer nrc's notion that macros should be able to generate IR. That seems like a completely reasonable solution for this and many future possibilities, without necessarily adding to the surface syntax of the language.
|
This comment has been minimized.
This comment has been minimized.
To be clear I meant registering them with
I have no idea what that would look like or that it is a better idea; it seems rather speculative (in the sense of "this might take years before a design is even agreed to") and more costly than the rather low-cost solution of |
This comment has been minimized.
This comment has been minimized.
I certainly agree with that. However, I don't think a concern is the appropriate mechanism here. A concern seems like "if this were resolved then I'd approve". Here, the issue is "this shouldn't go forward at all, 'merge' is the wrong target, I'd like to 'close' instead". That doesn't seem best handled by the mechanism of a "concern". |
This comment has been minimized.
This comment has been minimized.
|
@joshtriplett As a point of interest, could you direct me to the concerns that were raised that you mentioned previously? I've gone through the original RFC thread and am unsure what is being specifically referred to. Thanks. |
This comment has been minimized.
This comment has been minimized.
SoniEx2
commented
Jan 6, 2019
|
@rfcbot concern ergonomics and optimization/performance (non-rust example of reduced performance and ergonomics https://gist.github.com/SoniEx2/fc5d3614614e4e3fe131#file-special-lua ) idk if I'm using this right (note how some of the "desugaring" (actually I'd say it's quite the opposite of desugaring - goto is a primitive, loops desugar into goto) is quite awful) (also note that lua lacks labeled anything so it forces you to use goto. even then, I believe at least one break-block would still be required, but probably with cleaner "desugaring".) |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
I'm not sure if this is an argument in favour of stabilisation or against, but note that this is trivially easy to encode in stable Rust today:
So on the one hand, we should just stabilise this because it is barely growing the language, just eliding |
This comment has been minimized.
This comment has been minimized.
SoniEx2
commented
Jan 7, 2019
•
|
it seems kinda confusing and the label is unnecessary. breaking blocks is a lot less confusing and requires the label. I don't understand why you think breaking blocks is an anti-pattern. what applies to X doesn't necessarily apply to not-quite-X. I may be able to buy a computer for $299.99, but not $299.98, even tho they're "basically" the same. |
This comment has been minimized.
This comment has been minimized.
I think we disagree that LBV is an anti-pattern. At the end of the day we chose to imbue Rust with imperative control flow rather than just having Rust be a functional programming language. While I might have preferred to not have such control flow, it's fait accompli. The question is then whether LBV is somehow more unreadable or problematic than other imperative mechanisms in Rust. I don't think it is. While I think that functions should be kept short (vertically) and shallow (indentation), it's better to be long and shallow than long and deep. I find that LBV helps avoid depth in some of the more complicated flows. LBV also seems readable to me as it explicitly denotes where it will jump to, making the flow well understood. All in all, I find LBV to be one of the least problematic imperative control flows. |
This comment has been minimized.
This comment has been minimized.
SoniEx2
commented
Jan 7, 2019
these may look similar, but they're not quite the same. while the first is arguably an anti-pattern, the second is arguably not. kinda like |
This comment has been minimized.
This comment has been minimized.
|
@nrc That doesn't have quite the same behavior though: #48594 (comment) In particular, the behavior of some_macro! {
...
break;
...
}If |
This comment has been minimized.
This comment has been minimized.
Please try to communicate your concerns in a more positive and productive way. Mocking others doesn't get us anywhere, and makes people feel bad. We're all here because we want to make sure that Rust is the best programming language it can be, and part of that process is ensuring that the community is as positive and encouraging as possible. |
This comment has been minimized.
This comment has been minimized.
|
Perhaps I'm falling foul of some big misunderstanding. I won't pretend to be an expert in LLVM, Rust's internals, or similar such things. That said, I do have some rudimentary experience with compiler design and I'm confused as to what the concern is. If someone could explain things, I'd really appreciate that. The way I see things:
To me, this seems more like the intuitive completion of a set of features that Rust already has - generalizing those features for all (or at least more) blocks. In terms of concerns about this being too similar to Could anybody explain to me in more specific terms what problems exist? |
This comment has been minimized.
This comment has been minimized.
|
Procedurally, IMO it isn't appropriate to file I could have filed similar "I don't like this" concerns on other features I personally disagreed with (see e.g. uniform_paths), but I don't believe that infinite-filibuster is a productive way to do language design. If there are specific concerns about the way that this feature interacts with other parts of the language that should be discussed / resolved (e.g. "this seems like it could be obviated by |
This comment has been minimized.
This comment has been minimized.
|
@cramertj I would not have filed such a concern in that form if @Centril hadn't explicitly suggested it. (I personally would have preferred if FCP had not been proposed.) What would you suggest as the appropriate process for "this should be closed", if someone has filed a P-FCP with rfcbot for something other than "close"? "make sure that they are addressed / resolved appropriately" sounds equivalent to "this is going to be stabilized one day, what does it take to get there?". That doesn't leave a path in the flow for "this should never be stabilized, this should not be part of the language".
Then we'd need to change the process back to requiring all checkboxes checked to proceed.
I don't believe it is either. I'd like to find a path to conclude this, too, I just would like to see it concluded in a different direction. For the record, based on experiences with this RFC, I don't think it's a good idea again to respond to an RFC with a caveat of "we can evaluate/address during stabilization whether we should proceed", because it seems clear to me that doing so produces critical procedural issues like this. We need a path for saying "yes, I can see how this individual feature would make the language more expressive, but based on overall evaluation of the language, it doesn't carry its weight, and I don't want to further expand the surface area of the language in this way". I believe we need to regularly make that call, lest every proposed feature be seen as inevitable in some form and just a matter of quelling objections and persisting. |
This comment has been minimized.
This comment has been minimized.
SoniEx2
commented
Jan 7, 2019
|
I will repeat what I've said before because it seems to have been missed: #48594 (comment) I basically talked about the differences between using a loop and using a breaking block. mainly, breaking blocks have different syntax, (slightly) different semantics (with respect to unlabeled break at the very least), they signify different intent, and a few other minor things. |
This comment has been minimized.
This comment has been minimized.
SoniEx2
commented
Jan 7, 2019
|
does rfcbot support anticoncerns? |
This comment has been minimized.
This comment has been minimized.
Yeah, it's an unfortunate hazard of our current process that either accepting or rejecting a feature require full consensus of the appropriate team. When the lang team is as large as it is now, it's difficult to always achieve this-- I thought from the comments above that this was just missing code examples to motivate why this feature is important, but it now sounds like you agree that there is code that can be better written using this feature, but aren't convinced that it is worth the costs you see here. I'm not sure of a way to convince you that these cases are sufficient motivation, as it seems like continuing to provide examples (including the macro example, which is literally impossible to write in another style) isn't enough. Similarly, I'm fairly confident that I personally will remain convinced that this feature should be merged: IMO it not only pulls its weight through a variety of examples where it is the best/only option, but the language is actually simpler with its addition (since not allowing labelled blocks is surprising to me given that we allow other labeled constructs). If you agree with my above summary of your position, then it seems we're at an unfortunate (and, I believe, historic!) impass lacking a process. One option is to intepret the current rfcbot rules as I did above to mean "no checkbox signals your disagreement, three members are necessary to overrule the majority", but I don't think that's how the rules were meant when they were introduced, so I think it was disingenuous of me to suggest that you should follow this procedure (though I did it myself elsewhere). I've previously heard suggestions that we could introduce a time limit for features going from approved->implemented->stabilized, and that we should "auto-close" features which fall behind in an effort to avoid an ever-increasing backlog. Something like that could address this case, where I (and, I think, several others on the team) will not mark checkboxes to close, nor will you mark a checkbox to accept (I still even now feel afraid even saying this that I'm throwing away a last-ditch effort to convince you! I worry that with ever-growing teams we'll lose the ability to come to consensus on features, and that it will be hard to steer the language in a coherent fashion, particularly on the lang-design team. Team size limits seems like an obvious solution to this-- it's possible to receive input from a large number of people, but quite impossible to build absolute consensus among a sufficiently large group. Others will probably argue that contentious features shouldn't be merged in an effort to safeguard the language from misfeatures. I personally think the community is unlikely to let us make to many of those mistakes without adequate warning, but it's a thought. I'll try and start a separate thread to discuss the process evolution here, and in the meantime I'd ask that folks chiming in on this thread please only post if there are new, critical use-cases to consider that are notably different from those above, or if there is a significant unconsidered reason why this feature should not be added to the language. Reading through the whole history on these megathreads is difficult, but it becomes even more-so when posts are repeated over-and-over, or when the thread is filled with unhelpful commentary. (he says having now typed one of the longest comment sin the whole thread XD) TL;DR: I think we're stuck, we should have a process for this-- I'll start that conversation elsewhere and link it here. Otherwise, please don't comment unless you have significant new information that needs to be considered. |
This comment has been minimized.
This comment has been minimized.
I would honestly consider that a feature.
I still feel that many of the examples could be written in other ways. This does not add any unrepresentable expressiveness to the language. I originally felt that it could be motivated with sufficient examples, but the more examples I see that could use this feature, the more I find myself agreeing with @withoutboats that this feature simply shouldn't go into the language. (Also worth noting: @nrc's crate
I do think that's the correct procedure for "abstaining", but not for objecting.
I do typically find orthogonality arguments compelling, but this one in particular I find uncompelling, as personally I would have preferred not to have labeled loop breaks in the language either.
I worry not just about steering but about stopping. There's a certain inevitability that crops up sometimes, where the process seems focused on finding a path to "yes" and there's no graph edge in the flowchart that leads to "no", just "not yet". There have been many posts written in 2018 and 2019 talking about feature growth in the language, and I feel that in the language team we need to give serious consideration to the total surface area of the language. And I feel like we don't have good processes that encourage us to do that. |
This comment has been minimized.
This comment has been minimized.
To be very clear: it does do exactly this. There is currently no way to express this code that does not interfere with other control-flow constructs, which (as others have pointed out) is especially desirable in macros, where this would be the only construct which is untargetable via un-labeled breaks, allowing macro-authors to break from sections without risking an overlap with a user-provided |
This comment has been minimized.
This comment has been minimized.
SoniEx2
commented
Jan 8, 2019
•
|
it also makes code more readable as you don't have to zig-zag around (if we had no labels at all - see Lua example) or do weird stuff with loops. this also has a small performance benefit even tho llvm should be able to optimize zigzag code. |
This comment has been minimized.
This comment has been minimized.
Is that something we could dig into perhaps?
This line of reasoning I find strange (unless you wish to remove labeled loop breaks with an edition). It does not seem appropriate to base design decisions based on what you wished weren't in the language. It is there, and so we should consider whether this addition is coherent with that. Otherwise there are many things I might have done differently about Rust, but I should not and cannot.
Not yet is its own form of "no" in the sense that it won't get stabilized without a yes. Furthermore, there is a no: convince the rest of us that LBV is a bad idea / not sufficiently motivated for X, Y, and Z reasons. I have yet to hear many such concrete arguments at all. You have also demonstrated clearly here that there is no inevitability.
I personally feel that many of these posts are either about sustainability (but not as aptly worded as @nikomatsakis did...) or that many folks don't understand how the language team operates (i.e. we already do give serious consideration to the total surface area). The total surface syntax of Rust has probably actually shrunk over the last year, not grown. LBV doesn't increase that notably and an argument could be made that it actually shrinks the number of productions in the language and makes the syntax more uniform. |
This comment has been minimized.
This comment has been minimized.
|
Merely combining grammar productions does not shrink the surface area of the language. |
This comment has been minimized.
This comment has been minimized.
SoniEx2
commented
Jan 8, 2019
|
Reducing the number of conditional branches one can take is arguably shrinking the language's surface area. I don't think this particular feature goes either way, as such it's probably neutral. But e.g. things that unify language constructs (bool let, anyone?) do shrink surface area. |
This comment has been minimized.
This comment has been minimized.
traviscross
commented
Jan 11, 2019
|
For what it's worth, Common Lisp, which is similar to Rust in the sense that it's a multi-paradigm language with macros, has this feature (named (block foo
(return-from foo "value"))My sense is that in Common Lisp this feature is considered successful. It doesn't come up in conversations about features that make the language difficult to learn or implement. |
This comment has been minimized.
This comment has been minimized.
JohnBSmith
commented
Jan 12, 2019
|
There is the inclusion
For example, in Scheme the following emulation of (define call/cc call-with-current-continuation)
(define-syntax block
(syntax-rules ()
((_ label statements ...)
(call/cc (lambda (label) (begin statements ...))))))
(block foo
(display "Visible text")
(foo "value")
(display "Phantom text"))In Scheme, |
This comment has been minimized.
This comment has been minimized.
NN---
commented
Mar 3, 2019
|
Nemerle language has Named blocks functionality. return, break and continue are implemented as macros using this feature. |
Centril commentedFeb 27, 2018
•
edited
This is a tracking issue for RFC 2046 (rust-lang/rfcs#2046).
Steps:
Unresolved questions:
returnas the keyword instead ofbreak? rust-lang/rfcs#2046 (comment)break; call it resolved. #48594 (comment)