Skip to content

Commit 6b19da6

Browse files
committed
Auto merge of rust-lang#135494 - yotamofek:rustdoc-fmt-from_fn, r=<try>
Refactor `fmt::Display` impls in rustdoc This PR does a couple of things, with the intention of cleaning up and streamlining some of the `fmt::Display` impls in rustdoc: 1. Use the unstable [`fmt::from_fn`](rust-lang#117729) instead of open-coding it. 2. Replace bespoke implementations of `Itertools::format` with the method itself. 3. Some more minor cleanups - DRY, remove unnecessary calls to `Symbol::as_str()`, replace some `format!()` calls with lazier options The changes are mostly cosmetic but some of them might have a slight positive effect on performance.
2 parents 9f4d9dc + 16e9fe6 commit 6b19da6

File tree

10 files changed

+199
-287
lines changed

10 files changed

+199
-287
lines changed

src/librustdoc/clean/cfg.rs

+64-77
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use std::fmt::{self, Write};
77
use std::{mem, ops};
88

9+
use itertools::Itertools;
910
use rustc_ast::{LitKind, MetaItem, MetaItemInner, MetaItemKind, MetaItemLit};
1011
use rustc_data_structures::fx::FxHashSet;
1112
use rustc_feature::Features;
@@ -389,98 +390,84 @@ fn write_with_opt_paren<T: fmt::Display>(
389390
Ok(())
390391
}
391392

393+
impl Display<'_> {
394+
fn display_quantified_sub_cfgs(
395+
&self,
396+
fmt: &mut fmt::Formatter<'_>,
397+
sub_cfgs: &[Cfg],
398+
separator: &str,
399+
) -> fmt::Result {
400+
use fmt::Display as _;
401+
402+
let short_longhand = self.1.is_long() && {
403+
let all_crate_features =
404+
sub_cfgs.iter().all(|sub_cfg| matches!(sub_cfg, Cfg::Cfg(sym::feature, Some(_))));
405+
let all_target_features = sub_cfgs
406+
.iter()
407+
.all(|sub_cfg| matches!(sub_cfg, Cfg::Cfg(sym::target_feature, Some(_))));
408+
409+
if all_crate_features {
410+
fmt.write_str("crate features ")?;
411+
true
412+
} else if all_target_features {
413+
fmt.write_str("target features ")?;
414+
true
415+
} else {
416+
false
417+
}
418+
};
419+
420+
sub_cfgs
421+
.iter()
422+
.map(|sub_cfg| {
423+
fmt::from_fn(move |f| {
424+
if let (true, Cfg::Cfg(_, Some(feat))) = (short_longhand, sub_cfg) {
425+
if self.1.is_html() {
426+
write!(f, "<code>{feat}</code>")
427+
} else {
428+
write!(f, "`{feat}`")
429+
}
430+
} else {
431+
write_with_opt_paren(f, !sub_cfg.is_all(), Display(sub_cfg, self.1))
432+
}
433+
})
434+
})
435+
.format(separator)
436+
.fmt(fmt)
437+
}
438+
}
439+
392440
impl fmt::Display for Display<'_> {
393441
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
394442
match *self.0 {
395443
Cfg::Not(ref child) => match **child {
396444
Cfg::Any(ref sub_cfgs) => {
397445
let separator =
398446
if sub_cfgs.iter().all(Cfg::is_simple) { " nor " } else { ", nor " };
399-
for (i, sub_cfg) in sub_cfgs.iter().enumerate() {
400-
fmt.write_str(if i == 0 { "neither " } else { separator })?;
401-
write_with_opt_paren(fmt, !sub_cfg.is_all(), Display(sub_cfg, self.1))?;
402-
}
403-
Ok(())
447+
fmt.write_str("neither ")?;
448+
sub_cfgs
449+
.iter()
450+
.map(|sub_cfg| {
451+
fmt::from_fn(|fmt| {
452+
write_with_opt_paren(
453+
fmt,
454+
!sub_cfg.is_all(),
455+
Display(sub_cfg, self.1),
456+
)
457+
})
458+
})
459+
.format(separator)
460+
.fmt(fmt)
404461
}
405462
ref simple @ Cfg::Cfg(..) => write!(fmt, "non-{}", Display(simple, self.1)),
406463
ref c => write!(fmt, "not ({})", Display(c, self.1)),
407464
},
408465

409466
Cfg::Any(ref sub_cfgs) => {
410467
let separator = if sub_cfgs.iter().all(Cfg::is_simple) { " or " } else { ", or " };
411-
412-
let short_longhand = self.1.is_long() && {
413-
let all_crate_features = sub_cfgs
414-
.iter()
415-
.all(|sub_cfg| matches!(sub_cfg, Cfg::Cfg(sym::feature, Some(_))));
416-
let all_target_features = sub_cfgs
417-
.iter()
418-
.all(|sub_cfg| matches!(sub_cfg, Cfg::Cfg(sym::target_feature, Some(_))));
419-
420-
if all_crate_features {
421-
fmt.write_str("crate features ")?;
422-
true
423-
} else if all_target_features {
424-
fmt.write_str("target features ")?;
425-
true
426-
} else {
427-
false
428-
}
429-
};
430-
431-
for (i, sub_cfg) in sub_cfgs.iter().enumerate() {
432-
if i != 0 {
433-
fmt.write_str(separator)?;
434-
}
435-
if let (true, Cfg::Cfg(_, Some(feat))) = (short_longhand, sub_cfg) {
436-
if self.1.is_html() {
437-
write!(fmt, "<code>{feat}</code>")?;
438-
} else {
439-
write!(fmt, "`{feat}`")?;
440-
}
441-
} else {
442-
write_with_opt_paren(fmt, !sub_cfg.is_all(), Display(sub_cfg, self.1))?;
443-
}
444-
}
445-
Ok(())
446-
}
447-
448-
Cfg::All(ref sub_cfgs) => {
449-
let short_longhand = self.1.is_long() && {
450-
let all_crate_features = sub_cfgs
451-
.iter()
452-
.all(|sub_cfg| matches!(sub_cfg, Cfg::Cfg(sym::feature, Some(_))));
453-
let all_target_features = sub_cfgs
454-
.iter()
455-
.all(|sub_cfg| matches!(sub_cfg, Cfg::Cfg(sym::target_feature, Some(_))));
456-
457-
if all_crate_features {
458-
fmt.write_str("crate features ")?;
459-
true
460-
} else if all_target_features {
461-
fmt.write_str("target features ")?;
462-
true
463-
} else {
464-
false
465-
}
466-
};
467-
468-
for (i, sub_cfg) in sub_cfgs.iter().enumerate() {
469-
if i != 0 {
470-
fmt.write_str(" and ")?;
471-
}
472-
if let (true, Cfg::Cfg(_, Some(feat))) = (short_longhand, sub_cfg) {
473-
if self.1.is_html() {
474-
write!(fmt, "<code>{feat}</code>")?;
475-
} else {
476-
write!(fmt, "`{feat}`")?;
477-
}
478-
} else {
479-
write_with_opt_paren(fmt, !sub_cfg.is_simple(), Display(sub_cfg, self.1))?;
480-
}
481-
}
482-
Ok(())
468+
self.display_quantified_sub_cfgs(fmt, sub_cfgs, separator)
483469
}
470+
Cfg::All(ref sub_cfgs) => self.display_quantified_sub_cfgs(fmt, sub_cfgs, " and "),
484471

485472
Cfg::True => fmt.write_str("everywhere"),
486473
Cfg::False => fmt.write_str("nowhere"),

0 commit comments

Comments
 (0)