-
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
Weird chain formatting issues #2932
Comments
It looks even more weird when adding another call to the chain: stable fn f() -> CustomVec<u32> {
[1, 2, 3]
.iter()
.map(|&x| {
return x * 2;
})
.collect()
.into()
} nightly fn f() -> CustomVec<u32> {
[1, 2, 3]
.iter()
.map(|&x| {
return x * 2;
}).collect()
.into()
} |
I've noticed the exact same. My code was previously formatted like this: Client::new()
.request(
Request::get(&req.state().upstream)
.header(
header::ACCEPT,
HeaderValue::from_static(CONTENT_TYPE_GRAPH_V1),
)
.body(Body::empty())
.expect("unable to form request"),
)
.from_err::<Error>()
.and_then(|res| {
if res.status().is_success() {
future::ok(res)
} else {
future::err(format_err!(
"failed to fetch upstream graph: {}",
res.status()
))
}
})
.and_then(|res| res.into_body().concat2().from_err::<Error>())
.and_then(|body| {
let graph: Graph = serde_json::from_slice(&body)?;
Ok(HttpResponse::Ok()
.content_type(CONTENT_TYPE_GRAPH_V1)
.body(serde_json::to_string(&graph)?))
}) But new versions of rustfmt prefer the following: Client::new()
.request(
Request::get(&req.state().upstream)
.header(
header::ACCEPT,
HeaderValue::from_static(CONTENT_TYPE_GRAPH_V1),
).body(Body::empty())
.expect("unable to form request"),
).from_err::<Error>()
.and_then(|res| {
if res.status().is_success() {
future::ok(res)
} else {
future::err(format_err!(
"failed to fetch upstream graph: {}",
res.status()
))
}
}).and_then(|res| res.into_body().concat2().from_err::<Error>())
.and_then(|body| {
let graph: Graph = serde_json::from_slice(&body)?;
Ok(HttpResponse::Ok()
.content_type(CONTENT_TYPE_GRAPH_V1)
.body(serde_json::to_string(&graph)?))
}) I find the latter to be quite difficult to read. |
From an ergonomics point of view, I tend to use a duplicate line shortcut in this kind of code: something
.with_function(|| {
// ...
})
.add_stuff(1) // This is where I'd focus the cursor and duplicate line
.add_stuff(1) // <- and this pops out, so I can change the argument
// ... But with the new one something
.with_function(|| {
// ...
}).add_stuff(1) // This is where I'd focus the cursor and duplicate line
}).add_stuff(1) // <- but this pops out, which is broken syntax
// ... It's true I can go and delete the extra brackets, but it is annoying |
I'm seeing another strange artifact that feels similar: .txqptr
.read()
.dmatxqptr()
- .bits() << 2
+ .bits()
+ << 2 |
The Because there is a closure, identified as a block by https://github.com/rust-lang-nursery/rustfmt/blob/4bbfe0829d0ca4579c20c51100bb43c70f7c8e2d/src/chains.rs#L132, the newline is not added: @RReverser Looks like the option |
@scampi I don't think special-casing closures would be sufficient, logic needs to be modified more substantially (or removed) since blocks in the middle of chain are formatted equally poorly. |
Can you expand on the formatting of middle chain blocks ? I see the following at the moment:
|
This one is intentional - it was too easy to miss operators which were hidden in the chain.
This was deliberate, but maybe not optimal. I don't remember all the motivations - at the least I thought always putting a newline after |
I rather meant equal issues with function calls which take e.g. block expression and not closure as an argument - they're formatted just like in the original example in the issue, so I don't think special casing closures is going to cut it. |
Oh, it happens not only with closures and block expressions but also structs: fn f() -> CustomVec<u32> {
[1, 2, 3]
.iter()
.some_method(S {
x: 10,
y: 20,
z: 30,
}).collect()
.into()
} Moreover, it seems that this bug is now happening on stable too :( |
I have commented the The idea would be to better understand what needs fixing and a basis for further discussion. Observations
In addition to the ergonomics argument, my personal feeling is that removing the newline in cases of method chains (i.e., Removing the newline in cases of a block expression (i.e., The lone ordinal as shown in ExamplesMethod Chaindiff1 some_fuuuuuuuuunction()
.method_call_a(aaaaa, bbbbb, |c| {
let x = c;
x
- }).method_call_b(aaaaa, bbbbb, |c| {
+ })
+ .method_call_b(aaaaa, bbbbb, |c| {
let x = c;
x
}); diff2 aaaaaaaaaaaaaaaa
.map(|x| {
x += 1;
x
- }).filter(some_mod::some_filter)
+ })
+ .filter(some_mod::some_filter) diff3 match inner_meta_item.node {
ast::MetaItemKind::List(..) => rewrite_path(
context,
PathContext::Type,
None,
&inner_meta_item.ident,
shape,
- ).map_or(false, |s| s.len() + path.len() + 2 <= shape.width),
+ )
+ .map_or(false, |s| s.len() + path.len() + 2 <= shape.width),
_ => false,
} diff4 args.iter()
.filter(|arg| {
arg.to_expr()
.map(|e| match e.node {
ast::ExprKind::Closure(..) => true,
_ => false,
- }).unwrap_or(false)
- }).count()
+ })
+ .unwrap_or(false)
+ })
+ .count()
> 1 diff5 {
match x {
PushParam => {
// params are 1-indexed
stack.push(
mparams[match cur.to_digit(10) {
Some(d) => d as usize - 1,
None => return Err("bad param number".to_owned()),
- }].clone(),
+ }]
+ .clone(),
);
}
}
} Block Expressionsdiff6 let x = Foo {
field1: val1,
field2: val2,
- }.method_call()
+ }
+ .method_call()
.method_call(); diff7 let y = if cond {
val1
} else {
val2
- }.method_call();
+ }
+ .method_call(); Miscellaneousdiff8Regression of #2415 let base_url = (|| {
// stuff
Ok((|| {
// stuff
Some(value.to_string())
- })().ok_or("")?)
- })().unwrap_or_else(|_: Box<::std::error::Error>| String::from(""));
+ })()
+ .ok_or("")?)
+ })()
+ .unwrap_or_else(|_: Box<::std::error::Error>| String::from("")); diff9 .fold(
(String::new(), true),
|(mut s, need_indent), (kind, ref l)| {
if !l.is_empty() && need_indent {
s += &indent_str;
}
(s + l + "\n", !kind.is_string() || l.ends_with('\\'))
},
- ).0;
+ )
+ .0; |
A rule that would cause a line break in 1,2,4,5 (though not 3) and not 6,7,8 (borrowed from python's If you need to line break for one method, line break for all sibling methods in that chain. 7 is a canonical case where you wouldn't wrap |
This just landed on stable rust and it just created some really ugly files. A good example is what it did to our clap app definition: https://github.com/getsentry/semaphore/blob/474a29f39b4c90c5f1588fa9f469fe05be1c10be/src/cliapp.rs |
Rustfmt used to chain function calls in a consistent uniform fashion, e.g.:
But recently something has changed on nightly version and it started breaking the chain like below:
The text was updated successfully, but these errors were encountered: