Skip to content

Commit 9e1e35d

Browse files
Rollup merge of #152293 - ia0:try_blocks_heterogeneous, r=ytmimi
Format heterogeneous try blocks The tracking issue for `try_blocks_heterogeneous` is rust-lang/rust#149488. This follows the formatting of homogeneous try blocks (feature `try_blocks`) by considering `try bikeshed <type>` to be the equivalent of `try` (in particular a single "token"). An alternative would be to permit breaking between `bikeshed` and `<type>`, but given that those 2 elements are an explicitly temporary part of the syntax, it doesn't seem worth it. There also doesn't seem to be any existing precedent breaking between a keyword and a type. It also doesn't seem to be useful in practice, given that the type itself doesn't break (which is how it works for the return type of closures) and has more chances to dominate the length in case a break is necessary. Happy to adapt anything in case this formatting is not optimal. The test is also copied from homogeneous try blocks with 2 additional test cases to demonstrate the behavior with long types. See [#t-lang > try blocks @ 💬](https://rust-lang.zulipchat.com/#narrow/channel/213817-t-lang/topic/try.20blocks/near/572387493) for context.
2 parents ce2bda4 + ed53077 commit 9e1e35d

5 files changed

Lines changed: 109 additions & 2 deletions

File tree

src/expr.rs

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -385,8 +385,33 @@ pub(crate) fn format_expr(
385385
))
386386
}
387387
}
388-
// FIXME: heterogeneous try blocks, which include a type so are harder to format
389-
ast::ExprKind::TryBlock(_, Some(_)) => Err(RewriteError::Unknown),
388+
ast::ExprKind::TryBlock(ref block, Some(ref ty)) => {
389+
let keyword = "try bikeshed ";
390+
// 2 = " {".len()
391+
let ty_shape = shape
392+
.shrink_left(keyword.len())
393+
.and_then(|shape| shape.sub_width(2))
394+
.max_width_error(shape.width, expr.span)?;
395+
let ty_str = ty.rewrite_result(context, ty_shape)?;
396+
let prefix = format!("{keyword}{ty_str} ");
397+
if let rw @ Ok(_) =
398+
rewrite_single_line_block(context, &prefix, block, Some(&expr.attrs), None, shape)
399+
{
400+
rw
401+
} else {
402+
let budget = shape.width.saturating_sub(prefix.len());
403+
Ok(format!(
404+
"{prefix}{}",
405+
rewrite_block(
406+
block,
407+
Some(&expr.attrs),
408+
None,
409+
context,
410+
Shape::legacy(budget, shape.indent)
411+
)?
412+
))
413+
}
414+
}
390415
ast::ExprKind::Gen(capture_by, ref block, ref kind, _) => {
391416
let mover = if matches!(capture_by, ast::CaptureBy::Value { .. }) {
392417
"move "

tests/source/try_block.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// rustfmt-edition: 2018
2+
#![feature(try_blocks)]
23

34
fn main() -> Result<(), !> {
45
let _x: Option<_> = try {
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// rustfmt-edition: 2018
2+
#![feature(try_blocks_heterogeneous)]
3+
4+
fn main() -> Result<(), !> {
5+
let _x = try bikeshed Option<_> {
6+
4
7+
};
8+
9+
try bikeshed Result<_, _> {}
10+
}
11+
12+
fn baz() -> Option<i32> {
13+
if (1 == 1) {
14+
return try bikeshed Option<i32> {
15+
5
16+
};
17+
}
18+
19+
// test
20+
let x = try bikeshed Option<()> {
21+
// try blocks are great
22+
};
23+
24+
let y = try bikeshed Option<i32> {
25+
6
26+
}; // comment
27+
28+
let x = try /* Invisible comment */ bikeshed Option<()> {};
29+
let x = try bikeshed /* Invisible comment */ Option<()> {};
30+
let x = try bikeshed Option<()> /* Invisible comment */ {};
31+
32+
let x = try bikeshed Option<i32> { baz()?; baz()?; baz()?; 7 };
33+
34+
let x = try bikeshed Foo<Bar, Bar, Bar, Bar, Bar, Bar, Bar, Bar, Bar, Bar, Bar, Bar, Bar> { 1 + 1 + 1 };
35+
36+
let x = try bikeshed Foo<Bar, Bar, Bar, Bar, Bar, Bar, Bar, Bar, Bar, Bar, Bar, Bar, Bar, Bar> {};
37+
38+
return None;
39+
}

tests/target/try_block.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// rustfmt-edition: 2018
2+
#![feature(try_blocks)]
23

34
fn main() -> Result<(), !> {
45
let _x: Option<_> = try { 4 };
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// rustfmt-edition: 2018
2+
#![feature(try_blocks_heterogeneous)]
3+
4+
fn main() -> Result<(), !> {
5+
let _x = try bikeshed Option<_> { 4 };
6+
7+
try bikeshed Result<_, _> {}
8+
}
9+
10+
fn baz() -> Option<i32> {
11+
if (1 == 1) {
12+
return try bikeshed Option<i32> { 5 };
13+
}
14+
15+
// test
16+
let x = try bikeshed Option<()> {
17+
// try blocks are great
18+
};
19+
20+
let y = try bikeshed Option<i32> { 6 }; // comment
21+
22+
let x = try /* Invisible comment */ bikeshed Option<()> {};
23+
let x = try bikeshed /* Invisible comment */ Option<()> {};
24+
let x = try bikeshed Option<()> /* Invisible comment */ {};
25+
26+
let x = try bikeshed Option<i32> {
27+
baz()?;
28+
baz()?;
29+
baz()?;
30+
7
31+
};
32+
33+
let x = try bikeshed Foo<Bar, Bar, Bar, Bar, Bar, Bar, Bar, Bar, Bar, Bar, Bar, Bar, Bar> {
34+
1 + 1 + 1
35+
};
36+
37+
let x =
38+
try bikeshed Foo<Bar, Bar, Bar, Bar, Bar, Bar, Bar, Bar, Bar, Bar, Bar, Bar, Bar, Bar> {};
39+
40+
return None;
41+
}

0 commit comments

Comments
 (0)