Rustfmt: 格式化修复
摘要
- 修复各种格式化场景。
详情
2024 风格版本引入了对各种格式化场景的几项修复。
不要对齐项后或块末尾不相关的尾随注释
以前,rustfmt 会假定跟随带有尾随注释的项的行上的注释应该缩进以匹配尾随注释。现在已更改为这些注释不缩进。
风格版本 2021
pub const IFF_MULTICAST: ::c_int = 0x0000000800; // Supports multicast
// Multicast using broadcst. add.
pub const SQ_CRETAB: u16 = 0x000e; // CREATE TABLE
pub const SQ_DRPTAB: u16 = 0x000f; // DROP TABLE
pub const SQ_CREIDX: u16 = 0x0010; // CREATE INDEX
//const SQ_DRPIDX: u16 = 0x0011; // DROP INDEX
//const SQ_GRANT: u16 = 0x0012; // GRANT
//const SQ_REVOKE: u16 = 0x0013; // REVOKE
fn foo() {
let f = bar(); // Donec consequat mi. Quisque vitae dolor. Integer lobortis. Maecenas id nulla. Lorem.
// Id turpis. Nam posuere lectus vitae nibh. Etiam tortor orci, sagittis
// malesuada, rhoncus quis, hendrerit eget, libero. Quisque commodo nulla at
let b = baz();
let normalized = self.ctfont.all_traits().normalized_weight(); // [-1.0, 1.0]
// TODO(emilio): It may make sense to make this range [.01, 10.0], to align
// with css-fonts-4's range of [1, 1000].
}
风格版本 2024
pub const IFF_MULTICAST: ::c_int = 0x0000000800; // Supports multicast
// Multicast using broadcst. add.
pub const SQ_CRETAB: u16 = 0x000e; // CREATE TABLE
pub const SQ_DRPTAB: u16 = 0x000f; // DROP TABLE
pub const SQ_CREIDX: u16 = 0x0010; // CREATE INDEX
//const SQ_DRPIDX: u16 = 0x0011; // DROP INDEX
//const SQ_GRANT: u16 = 0x0012; // GRANT
//const SQ_REVOKE: u16 = 0x0013; // REVOKE
fn foo() {
let f = bar(); // Donec consequat mi. Quisque vitae dolor. Integer lobortis. Maecenas id nulla. Lorem.
// Id turpis. Nam posuere lectus vitae nibh. Etiam tortor orci, sagittis
// malesuada, rhoncus quis, hendrerit eget, libero. Quisque commodo nulla at
let b = baz();
let normalized = self.ctfont.all_traits().normalized_weight(); // [-1.0, 1.0]
// TODO(emilio): It may make sense to make this range [.01, 10.0], to align
// with css-fonts-4's range of [1, 1000].
}
不要缩进注释中的字符串
以前,rustfmt 会错误地尝试格式化注释中的字符串。
原始
pub fn main() {
/* let s = String::from(
"
hello
world
",
); */
}
风格版本 2021
pub fn main() {
/* let s = String::from(
"
hello
world
",
); */
}
风格版本 2024
与原始版本无变化。
长字符串不会阻止格式化表达式
在某些情况下,长字符串以前会阻止表达式被格式化。
风格版本 2021
fn main() {
let value = if x == "Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum." { 0 } else {10};
let x = Testing {
foo: "long_long_long_long_long_long_long_lo_long_long_long_long_long_long__long_long_long_long_long_long_",
bar: "long_long_long_long_long_long_long_long_long_long_lo_long_long_lolong_long_long_lo_long_long_lolong_long_long_lo_long_long_lo",
};
}
风格版本 2024
fn main() {
let value = if x
== "Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
{
0
} else {
10
};
let x = Testing {
foo: "long_long_long_long_long_long_long_lo_long_long_long_long_long_long__long_long_long_long_long_long_",
bar: "long_long_long_long_long_long_long_long_long_long_lo_long_long_lolong_long_long_lo_long_long_lolong_long_long_lo_long_long_lo",
};
}
修复了 impl 块中泛型的缩进
impl
项中的泛型具有过多的缩进。
风格版本 2021
impl<
Target: FromEvent<A> + FromEvent<B>,
A: Widget2<Ctx = C>,
B: Widget2<Ctx = C>,
C: for<'a> CtxFamily<'a>,
> Widget2 for WidgetEventLifter<Target, A, B>
{
type Ctx = C;
type Event = Vec<Target>;
}
风格版本 2024
impl<
Target: FromEvent<A> + FromEvent<B>,
A: Widget2<Ctx = C>,
B: Widget2<Ctx = C>,
C: for<'a> CtxFamily<'a>,
> Widget2 for WidgetEventLifter<Target, A, B>
{
type Ctx = C;
type Event = Vec<Target>;
}
在格式化复杂的 fn
时使用正确的缩进
在某些情况下,复杂的 fn
签名可能会最终出现不寻常的缩进,现在已修复。
风格版本 2021
fn build_sorted_static_get_entry_names(
mut entries: Vec<(u8, &'static str)>,
) -> (impl Fn(
AlphabeticalTraversal,
Box<dyn dirents_sink::Sink<AlphabeticalTraversal>>,
) -> BoxFuture<'static, Result<Box<dyn dirents_sink::Sealed>, Status>>
+ Send
+ Sync
+ 'static) {
}
风格版本 2024
fn build_sorted_static_get_entry_names(
mut entries: Vec<(u8, &'static str)>,
) -> (
impl Fn(
AlphabeticalTraversal,
Box<dyn dirents_sink::Sink<AlphabeticalTraversal>>,
) -> BoxFuture<'static, Result<Box<dyn dirents_sink::Sealed>, Status>>
+ Send
+ Sync
+ 'static
) {
}
避免嵌套元组索引表达式中出现多余的空格
嵌套元组索引表达式会错误地包含一个额外的空格。
风格版本 2021
fn main() {
let _ = ((1,),).0 .0;
}
风格版本 2024
fn main() {
let _ = ((1,),).0.0;
}
在带有分号的 match 块内结束 return/break/continue
match arm 中块内的 return
、break
或 continue
错误地缺少分号。
风格版本 2021
fn foo() {
match 0 {
0 => {
return AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
}
_ => "",
};
}
风格版本 2024
fn foo() {
match 0 {
0 => {
return AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA;
}
_ => "",
};
}
长数组和切片模式现在被换行
长数组和切片模式以前没有被正确地换行。
风格版本 2021
fn main() {
let [aaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, cccccccccccccccccccccccccc, ddddddddddddddddddddddddd] =
panic!();
}
风格版本 2024
fn main() {
let [
aaaaaaaaaaaaaaaaaaaaaaaaaa,
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb,
cccccccccccccccccccccccccc,
ddddddddddddddddddddddddd,
] = panic!();
}
将最后一个表达式语句格式化为表达式
块中的最后一个语句(它是表达式)现在被格式化为表达式。
风格版本 2021
fn main() {
let toto = || {
if true {
42
} else {
24
}
};
{
T
}
}
风格版本 2024
fn main() {
let toto = || {
if true { 42 } else { 24 }
};
{ T }
}
函数调用和宏调用之间相同的格式化
某些格式化现在在宏调用中与在函数调用中相同。
风格版本 2021
fn main() {
macro_call!(HAYSTACK
.par_iter()
.find_any(|&&x| x[0] % 1000 == 999)
.is_some());
fn_call(
HAYSTACK
.par_iter()
.find_any(|&&x| x[0] % 1000 == 999)
.is_some(),
);
}
风格版本 2024
fn main() {
macro_call!(
HAYSTACK
.par_iter()
.find_any(|&&x| x[0] % 1000 == 999)
.is_some()
);
fn_call(
HAYSTACK
.par_iter()
.find_any(|&&x| x[0] % 1000 == 999)
.is_some(),
);
}
为具有单个循环体的闭包强制使用块闭包
具有单个循环的闭包现在被格式化为块表达式。
风格版本 2021
fn main() {
thread::spawn(|| loop {
println!("iteration");
});
}
风格版本 2024
fn main() {
thread::spawn(|| {
loop {
println!("iteration");
}
});
}
where 子句中的空行现在被移除
where
子句中的空行现在被移除。
风格版本 2021
fn foo<T>(_: T)
where
T: std::fmt::Debug,
T: std::fmt::Display,
{
}
风格版本 2024
fn foo<T>(_: T)
where
T: std::fmt::Debug,
T: std::fmt::Display,
{
}
修复了带有属性的 let-else 语句的格式化
如果 let-else 语句具有属性,则会导致 else
子句错误地单独换行 else
部分。
风格版本 2021
fn main() {
#[cfg(target_os = "linux")]
let x = 42
else {
todo!()
};
// This is the same without an attribute.
let x = 42 else { todo!() };
}
风格版本 2024
fn main() {
#[cfg(target_os = "linux")]
let x = 42 else { todo!() };
// This is the same without an attribute.
let x = 42 else { todo!() };
}
枚举变体文档注释换行的差一错误
当使用 wrap_comments
功能时,注释在列宽上被换行了差一错误。
原始
pub enum Severity {
/// But here, this comment is 120 columns wide and the formatter wants to split it up onto two separate lines still.
Error,
/// This comment is 119 columns wide and works perfectly. Lorem ipsum. lorem ipsum. lorem ipsum. lorem ipsum lorem.
Warning,
}
风格版本 2021
pub enum Severity {
/// But here, this comment is 120 columns wide and the formatter wants to split it up onto two separate lines
/// still.
Error,
/// This comment is 119 columns wide and works perfectly. Lorem ipsum. lorem ipsum. lorem ipsum. lorem ipsum lorem.
Warning,
}
风格版本 2024
pub enum Severity {
/// But here, this comment is 120 columns wide and the formatter wants to split it up onto two separate lines still.
Error,
/// This comment is 119 columns wide and works perfectly. Lorem ipsum. lorem ipsum. lorem ipsum. lorem ipsum lorem.
Warning,
}
format_macro_matchers
的差一错误
当使用 format_macro_matchers
功能时,matcher 在列宽上被换行了差一错误。
风格版本 2021
macro_rules! test {
($aasdfghj:expr, $qwertyuiop:expr, $zxcvbnmasdfghjkl:expr, $aeiouaeiouaeio:expr, $add:expr) => {{
return;
}};
}
风格版本 2024
macro_rules! test {
(
$aasdfghj:expr, $qwertyuiop:expr, $zxcvbnmasdfghjkl:expr, $aeiouaeiouaeio:expr, $add:expr
) => {{
return;
}};
}
修复了在 match =>
后的注释中使用 =>
时的失败
在某些情况下,如果注释在 match 表达式中的 =>
之后包含 =>
,则会导致格式化失败。
风格版本 2021
fn main() {
match a {
_ =>
// comment with =>
{
println!("A")
}
}
}
风格版本 2024
fn main() {
match a {
_ =>
// comment with =>
{
println!("A")
}
}
}
match 表达式中的多个内部属性缩进不正确
match 表达式中的多个内部属性被错误地缩进。
风格版本 2021
pub fn main() {
match a {
#![attr1]
#![attr2]
_ => None,
}
}
风格版本 2024
pub fn main() {
match a {
#![attr1]
#![attr2]
_ => None,
}
}
迁移
此更改可以通过使用 2024 Edition 运行 cargo fmt
或 rustfmt
自动应用。有关迁移以及风格版本如何工作的更多信息,请参阅风格版本章节。