-
Notifications
You must be signed in to change notification settings - Fork 888
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
rust-lang/style-team#189: rhs-should-use-indent-of-last-line-of-lhs #6305
base: master
Are you sure you want to change the base?
rust-lang/style-team#189: rhs-should-use-indent-of-last-line-of-lhs #6305
Conversation
e79db51
to
fa8b854
Compare
8e01441
to
23bfe0e
Compare
fb84edc
to
6da81be
Compare
let new_shape = shape | ||
.block_indent(tab_spaces) | ||
.saturating_sub_width(tab_spaces); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you explain the call to .saturating_sub_width(tab_spaces)
. I'm not sure if that's necessary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Without saturating_sub_width,
impl SomeType {
fn method(&mut self) {
self.array[array_index as usize]
.as_mut()
.expect("thing must exist")
.extra_info =
long_long_long_long_long_long_long_long_long_long_long_long_long_long_long;
}
}
is formatted to
impl SomeType {
fn method(&mut self) {
self.array[array_index as usize]
.as_mut()
.expect("thing must exist")
.extra_info = long_long_long_long_long_long_long_long_long_long_long_long_long_long_long;
}
}
and throws
line formatted, but exceeded maximum width (maximum: 100 (see `max_width` option), found: 101)
rather than
impl SomeType {
fn method(&mut self) {
self.array[array_index as usize]
.as_mut()
.expect("thing must exist")
.extra_info =
long_long_long_long_long_long_long_long_long_long_long_long_long_long_long;
}
}
I think the remaining width is not accounted for properly if I only use block_indent
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you explain why we're using tab_spaces
? What happens if we don't use .saturating_sub_width(tab_spaces)
, but the rhs was even longer? Does it wrap correctly then?
Part of me wonders if the shape
is off to begin with.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the shape that was used before adding extra block_indent is
old shape = Shape { width: 91, indent: Indent { block_indent: 8, alignment: 0 }, offset: 0 }
and the new shape with block_indent but without saturating_sub_width is
new shape = Shape { width: 91, indent: Indent { block_indent: 12, alignment: 0 }, offset: 0
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the new shape is also the shape of the last line of lhs
.extra_info = long_long_long_long_long_long_long_long_long_long_long_long_long_long_long;
has 12 spaces before .extra_info
and .extra_info = long_long_long_long_long_long_long_long_long_long_long_long_long_long_long;
is 89 chars. So the remaining width shouldn't be 91, but 87
i.e. when indent was 8 spaces, width = 91, max width = 100, so
width = max - indent - 1
when indent is 12, width = 100 - 12 - 1 =87
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ytmimi I think the above should answer your last question in this PR. Can you take a look?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the detailed explanation. I didn't have time to revisit this PR over the weekend, but I plan on giving this another look later this week
src/expr.rs
Outdated
let extra_indent_string = new_shape.to_string(&context.config).to_string(); | ||
if last_line.starts_with(&extra_indent_string) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We shouldn't need to allocate a string with to_string()
. We should be able to call as_ref()
:
let extra_indent_string = new_shape.to_string(&context.config).to_string(); | |
if last_line.starts_with(&extra_indent_string) { | |
let extra_indent_string = new_shape.to_string(&context.config); | |
if last_line.starts_with(extra_indent_string.as_ref()) { |
src/expr.rs
Outdated
} | ||
}; | ||
let shape = if context.config.style_edition() >= StyleEdition::Edition2024 { | ||
get_lhs_last_line_shape() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm wondering if get_lhs_last_line_shape
is the right name. Technically what we're doing here is getting the shape used to format the rhs
, but it's based on the lhs
indentation. If you think you can come up with a succinct name that conveys that meaning that would be great!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in that case I will just call it get_rhs_shape, leave the implementation details out of the naming
@@ -278,6 +278,12 @@ impl Shape { | |||
offset_indent.to_string_inner(config, 0) | |||
} | |||
|
|||
pub(crate) fn to_string(&self, config: &Config) -> Cow<'static, str> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably worth adding a doc comment so that we know that this function gives us a single line of indentation.
6da81be
to
24509fe
Compare
src/expr.rs
Outdated
use rustc_ast::{ForLoopKind, MatchKind, ast, ptr, token}; | ||
use rustc_ast::{ast, ptr, token, ForLoopKind, MatchKind}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this was rebased correctly. The imports should not have changed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know, I am resolving some merge conflicts. Give me a few minutes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So the mismatch was due to my formatter (Neoformat using neovim) using a different version of rustfmt than nightly the current master
f389fa1
to
58ca556
Compare
Thank you both for the work on this, just noting I've added some labels to indicate the criticality of this one as it ties into 2024 deliverables. I can help with the review if beneficial |
Hey @calebcartwright now I am just waiting for a second look from @ytmimi. Do let me know if you see any changes I should make |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are a few other test cases that I think we should add:
impl SomeType {
fn method(&mut self) {
self.array[array_index as usize]
.as_mut()
.expect("thing must exist")
.extra_info = Some(ExtraInfo {
parent,
count: count as u16,
children: children.into_boxed_slice(),
}) + Some(ExtraInfo {
parent,
count: count as u16,
children: children.into_boxed_slice(),
});
}
}
impl SomeType {
fn method(&mut self) {
self.array[array_index as usize]
.as_mut()
.expect("thing must exist")
.extra_info =
long_long_long_long_long_long_long_long_long_long_long_long_long_long_long
.as_mut()
.another_call()
.get_extra_info();
}
}
impl SomeType {
fn method(&mut self) {
self.array[array_index as usize]
.as_mut()
.expect("thing must exist")
.extra_info =
long_long_long_long_long_long_long_long_long_long_long_long_long_long_long
.as_mut()
.another_call()
.get_extra_info() + Some(ExtraInfo {
parent,
count: count as u16,
children: children.into_boxed_slice(),
});
}
}
just checking for a status on this one, what's pending? |
For me, I'd like to confirm the formatting for the extra test cases mentioned in #6305 (comment). Assuming those get formatted as expected I think we're good to go for assignments. @calebcartwright we may also need to tweak how we format binary expressions, but I'm not 100% sure. Just going based off of rust-lang/style-team#189 (comment). For example: impl SomeType {
fn method(&mut self) {
self.array[array_index as usize]
.as_mut()
.expect("thing must exist")
.extra_info +
long_long_long_long_long_long_long_long_long_long_long_long_long_long_long
.as_mut()
.another_call()
.get_extra_info();
// ^^^ is this the right level of indentation to use for the `rhs` of the binary expression?
}
} If we need to make updates to binary expression formatting, that might be better to do in a follow up PR. |
if there's a set of snippets where we'd like style to give a perspective then i'm happy to bring that before the team, and we do have a meeting later today. Do the last two comments cover all the remaining questions or are there others? |
No outstanding questions besides my last two comments. |
We reviewed this (the formatting improvements provided by this PR) in the t-style meeting yesterday and overall were pleased with the results. There were some thoughts on potential future improvements, and one potential issue/bug observed with the way this proposed implementation formats one of the snippets in because this input 👇 impl SomeType {
fn method(&mut self) {
self.array[array_index as usize]
.as_mut()
.expect("thing must exist")
.extra_info =
long_long_long_long_long_long_long_long_long_long_long_long_long_long_long
.as_mut()
.another_call()
.get_extra_info() + Some(ExtraInfo {
parent,
count: count as u16,
children: children.into_boxed_slice(),
});
}
} is getting formatted without indentation on the impl SomeType {
fn method(&mut self) {
self.array[array_index as usize]
.as_mut()
.expect("thing must exist")
.extra_info = long_long_long_long_long_long_long_long_long_long_long_long_long_long_long
.as_mut()
.another_call()
.get_extra_info() + Some(ExtraInfo {
parent,
count: count as u16,
children: children.into_boxed_slice(),
});
}
} that's something I'd like to see if we can get addressed ASAP so we can get this merged and into nightly |
We've been discussing this item quite a bit more in the style team meetings, and reached a decision that we only want to move forward with the indent change around assignment operators (so for our purposes within rustfmt we'd only need to look at assignment and assignmentop expressions). I had extended what was done here to also directly support binary expressions, and we found that the results were mixed in more complex binary expression trees and felt we'd need some more nuanced rules that better account for expression tree structure and/or accounted for operator precedence rules. We are hitting crunch time for the edition items, so if we're a bit stalled here then I may grab some commits from this PR branch and/or add co-authors on commits on a PR of my own to ensure we get it through |
Pull Request Template
Checklist
cargo test
passesRelated Issues/PRs
rust-lang/style-team#189
Changes
Make sure that the rhs is formatted using the indentation of the last line of lhs, as opposed to the first line
Testing
added a test case