-
Notifications
You must be signed in to change notification settings - Fork 898
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
let-else formatting tracking issue #4914
Comments
As discussed in Zulip, we probably want to format this using the same rules for For short, one-statement diverging blocks (e.g. let pat = expr else { block }; For blocks that don't fit, or multi-statement blocks: let pat = expr else {
block
}; If the If |
Does that mean formatting like this? let pat = foo
.bar()
.bar()
.bar()
.bar()
.bar() else {
block();
return more
}; It works well when |
Good point. In the circumstance, if we're wrapping the expression anyway, I wonder if we should wrap the else to the start of the following line (outdented to match the let). |
If the expression needs more than one line, but the last line is not indented (in particular because it's let pat = ({
block();
bar
}) else {
return more
}; |
Please consider putting the let pat = expr else {
block
}; It is: let pat = expr
else {
block
}; MotivationIn the current version of Rust there are some constructs that follow a structure similar to this:
Here, the bindings are only visible in the block right after the keyword. Some examples: if let Some(x) = map.get(key) {
// x only lives here
}
for n in 0..10 {
// n only lives here
}
while let Some(item) = iter.next() {
// item only lives here
}
let Some(data2) = data else {
return Err(MissingData);
} At first sight, it looks that let Some(data) = data
else {
return Err(MissingData);
} Since It is also closer to how Similar to let x = if y { 0 } else { 1 };
let Some(x) = get_x() else { return }; Examples from the RFC
Examples from commentsFrom: #4914 (comment) Original: let pat = foo
.bar()
.bar()
.bar()
.bar()
.bar() else {
block();
return more
}; Proposed: let pat = foo
.bar()
.bar()
.bar()
.bar()
.bar()
else {
block();
return more
}; |
Appreciate all the input about the default formatting, but this really isn't the place to hammer that out. Ultimately the rules will need to be codified in the Rust Style Guide (and if someone wanted to open a PR over there for me that'd be great!) and that'll be a better place to discuss/debate the specifics. rustfmt typically has to take an iterative approach to handling new syntax, which typically starts with just spitting back out whatever was there before (via the associated span). Once the rules have solidified in the style guide we then update rustfmt with the corresponding formatting implementation. However, we then also have to account for things like comments, interactions with configuration options, and other pieces that aren't really captured in the style guide and discussions about preferred default formatting. I've opened this issue to track the bucket of work specific to implementation within rustfmt, but do not want this issue to be used for the style rules. |
Opened a style guide PR at rust-lang/style-team#165 |
I've found an example where rustfmt creates non-fixpoint output: #5213 |
Thanks for the other report and cross posting, though worth noting it's not actually related. rustfmt isn't touching let-else's yet, and in a macro context that leave-alone behavior is hitting a separate, unrelated bug that's been around for quite a long a while. |
My two cents from having used this for some time: I'm generally in favor of making the In my own code, I've always been happy to have the "body" of the else on a following line: let Some(x) = foo else {
return;
} that makes it stand-out to me. On the other hand, I recently encountered a long expression let Some((aaaaaaaaaaaaa, bbbbbbbbbbbbbbb, cccccccccccccc)) =
foo else {
return;
}; and that looked very bad to me, so I reformatted it to let Some((aaaaaaaaaaaaa, bbbbbbbbbbbbbbb, cccccccccccccc)) =
foo
else {
return
}; while the let Some(x) = foo
else { return; } I'm of mixed minds about very short cases like this: let Some(x) = foo else { return; } I can imagine scenarios where that compact formatting would be useful, but I think it'd be fragile, and I feel like I might come to value knowing that the UPDATE: Reading over my comment, I'm finding myself more and more of the opinion that the else should always be on its own line. It's still quite compact. |
To expand on this: I personally find that "scan for early return of some kind" is a fairly common thing that I do when debugging. I greatly appreciate |
One thing I'll add to this, @nikomatsakis, is that I find myself writing that pretty often, but it doesn't actually compile. It needs to be let Some(x) = foo
else { return; }; So I keep wondering if we should make a language change to not require that final Or at least let Some(x) = foo
else { return }; But I think that's against the normal rustfmt rules for blocks. |
Friendly reminder that this is the implementation tracking issue, and discussion around style rules should be directed towards the fmt-rfcs/style guide repo (specifically in the open PR rust-lang/style-team#165) |
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
Hello, Would it be possible for rustfmt to be not try to format let-else blocks for the moment? Thanks :) |
@leana8959 - rustfmt does not attempt to format let else statements whatsoever; it currently emits whatever the developer wrote, exactly as they wrote it. The only other alternative would be for rustfmt to delete those statements, which obviously isn't viable. The erroring behavior is fairly core to rustfmt and isn't really something we can/will change, especially now that the Style Team exists, formatting rules have been codified, and we've nearly finished the formatting implementation. If you/the developer have left trailing whitespace somewhere within a let else statement then your options are to either remove the whitespace manually/via editor features, or to instruct rustfmt to skip the statement altogether, e.g. https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=7398f01f51aa35f39baf8d49df07efdc |
Just to add a data point here: I was just reviewing some code that used let-else, and because the |
Any progress? |
I'm locking the issue because its only remaining utility is for the rustfmt team to inform subscribers when there's an update, and any additional comments from others are only going to add noise for those subscribers. Again, I understand the frustration and appreciate the desire for formatting. It's unfortunate we found ourselves in a situation without a clearly designated team that owned the decision around what the style was supposed to be. In the absence of an operable time machine there's really nothing that can be done about the past. However, the root cause has been resolved, and we're working through the backlog of things that had built up in the absence of that resolution. @Braymatter re:
This isn't really the right place for this, but it looks like your main issue is that you've got your editor configured to use a 2-space indent, while you're running rustfmt with the default 4-space indent. I'd suggest it's unwise to have different tools dueling on that front and encourage you to update one or the other to be consistent. Furthermore, it's that 2-space editor setting that's resulting in the offset for your |
It was brought to my attention earlier that some of the latest status updates on this, while linked within the thread, weren't as clear/apparent as they could be. As such I've updated the checkbox items with those links and commentary to make the current status easier to find. I will also add that we are tantalizingly close, and ask that folks bear with us just a bit longer. |
Using this as our own formatting tracking issue given that the RFC for let-else statements has been merged. This issue will be used to track the overall implementation within rustfmt whereas discussion on the default style should occur in the Rust Style Guide repo that defines the formatting spec rustfmt applies (link to PR/issue in style guide to-be-added)
Broadly this work will entail:
let-else
formatting #5690)let-else
formatting #5690)let-else
formatting #5690 - "short" config option for let-else statements? #5684)Edit - Updated to outline the high level steps and differentiate between style rules and rustfmt implementation
The text was updated successfully, but these errors were encountered: