Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 79d9fa0

Browse files
committed
Auto merge of rust-lang#116583 - saethlin:inline-small-core-fns, r=<try>
Add #[inline] to small functions in core I'm adding a new case to the definition of cross-crate-inlinable; we know that making the definition too broad causes huge regressions in incremental builds. So implementing broader heuristics as a machine-applicable lint means that I can `x fix --stage 1 library/core` to apply the new heuristic just to the standard library. I expect that applying the broader heuristic just to the standard library will have a different effect than applying the change globally.
2 parents c1ccc29 + 4edca85 commit 79d9fa0

40 files changed

+182
-6
lines changed

compiler/rustc_builtin_macros/src/deriving/debug.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ use rustc_span::symbol::{sym, Ident, Symbol};
99
use rustc_span::Span;
1010
use thin_vec::{thin_vec, ThinVec};
1111

12+
use rustc_ast::ItemKind;
13+
use rustc_ast::VariantData;
14+
1215
pub fn expand_deriving_debug(
1316
cx: &mut ExtCtxt<'_>,
1417
span: Span,
@@ -20,6 +23,21 @@ pub fn expand_deriving_debug(
2023
// &mut ::std::fmt::Formatter
2124
let fmtr = Ref(Box::new(Path(path_std!(fmt::Formatter))), ast::Mutability::Mut);
2225

26+
let mut attributes = ThinVec::new();
27+
if let Annotatable::Item(item) = item {
28+
match &item.kind {
29+
ItemKind::Struct(VariantData::Unit(_), _) => {
30+
attributes = thin_vec![cx.attr_word(sym::inline, span)];
31+
}
32+
ItemKind::Enum(EnumDef { variants }, _) => {
33+
if variants.iter().all(|v| matches!(v.data, VariantData::Unit(_))) {
34+
attributes = thin_vec![cx.attr_word(sym::inline, span)];
35+
}
36+
}
37+
_ => {}
38+
}
39+
}
40+
2341
let trait_def = TraitDef {
2442
span,
2543
path: path_std!(fmt::Debug),
@@ -33,7 +51,7 @@ pub fn expand_deriving_debug(
3351
explicit_self: true,
3452
nonself_args: vec![(fmtr, sym::f)],
3553
ret_ty: Path(path_std!(fmt::Result)),
36-
attributes: ast::AttrVec::new(),
54+
attributes,
3755
fieldless_variants_strategy:
3856
FieldlessVariantsStrategy::SpecializeIfAllVariantsFieldless,
3957
combine_substructure: combine_substructure(Box::new(|a, b, c| {

compiler/rustc_mir_transform/messages.ftl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ mir_transform_requires_unsafe = {$details} is unsafe and requires unsafe {$op_in
4242
}
4343
.not_inherited = items do not inherit unsafety from separate enclosing items
4444
45+
mir_transform_small_fn_without_inline = this function looks small ({$statements}) but doesn't have #[inline], consider adding it
46+
.suggestion = add the inline attribute
47+
4548
mir_transform_target_feature_call_label = call to function with `#[target_feature]`
4649
mir_transform_target_feature_call_note = can only be called if the required target features are available
4750

compiler/rustc_mir_transform/src/cross_crate_inline.rs

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,14 +55,39 @@ fn cross_crate_inlinable(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
5555
}
5656

5757
let mir = tcx.optimized_mir(def_id);
58-
let mut checker =
59-
CostChecker { tcx, callee_body: mir, calls: 0, statements: 0, landing_pads: 0, resumes: 0 };
58+
let mut checker = CostChecker {
59+
tcx,
60+
callee_body: mir,
61+
calls: 0,
62+
statements: 0,
63+
landing_pads: 0,
64+
resumes: 0,
65+
branches: 0,
66+
asserts: 0,
67+
};
6068
checker.visit_body(mir);
61-
checker.calls == 0
69+
let is_leaf = checker.calls == 0
6270
&& checker.resumes == 0
6371
&& checker.landing_pads == 0
6472
&& checker.statements
65-
<= tcx.sess.opts.unstable_opts.cross_crate_inline_threshold.unwrap_or(100)
73+
<= tcx.sess.opts.unstable_opts.cross_crate_inline_threshold.unwrap_or(100);
74+
75+
let is_trivial_wrapper = checker.calls == 1
76+
&& checker.resumes == 0
77+
&& checker.landing_pads == 0
78+
&& mir.basic_blocks.len() == 2;
79+
80+
if is_trivial_wrapper {
81+
let span = tcx.def_span(def_id);
82+
if !span.from_expansion() {
83+
tcx.sess.emit_warning(crate::errors::SuggestAddingInline {
84+
place: span,
85+
suggest_inline: span.with_hi(span.lo()),
86+
statements: checker.statements,
87+
});
88+
}
89+
}
90+
is_leaf
6691
}
6792

6893
struct CostChecker<'b, 'tcx> {
@@ -72,6 +97,8 @@ struct CostChecker<'b, 'tcx> {
7297
statements: usize,
7398
landing_pads: usize,
7499
resumes: usize,
100+
branches: usize,
101+
asserts: usize,
75102
}
76103

77104
impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> {
@@ -105,7 +132,7 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> {
105132
}
106133
}
107134
TerminatorKind::Assert { unwind, .. } => {
108-
self.calls += 1;
135+
self.asserts += 1;
109136
if let UnwindAction::Cleanup(_) = unwind {
110137
self.landing_pads += 1;
111138
}
@@ -117,6 +144,10 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> {
117144
self.landing_pads += 1;
118145
}
119146
}
147+
TerminatorKind::SwitchInt { .. } => {
148+
self.statements += 1;
149+
self.branches += 1;
150+
}
120151
TerminatorKind::Return => {}
121152
_ => self.statements += 1,
122153
}

compiler/rustc_mir_transform/src/errors.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,3 +278,13 @@ pub(crate) struct MustNotSuspendReason {
278278
pub span: Span,
279279
pub reason: String,
280280
}
281+
282+
#[derive(Diagnostic)]
283+
#[diag(mir_transform_small_fn_without_inline)]
284+
pub struct SuggestAddingInline {
285+
#[primary_span]
286+
pub place: Span,
287+
#[suggestion(code = "#[inline]\n", applicability = "machine-applicable")]
288+
pub suggest_inline: Span,
289+
pub statements: usize,
290+
}

library/core/src/alloc/layout.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,7 @@ impl Error for LayoutError {}
482482
// (we need this for downstream impl of trait Error)
483483
#[stable(feature = "alloc_layout", since = "1.28.0")]
484484
impl fmt::Display for LayoutError {
485+
#[inline]
485486
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
486487
f.write_str("invalid parameters to Layout::from_size_align")
487488
}

library/core/src/alloc/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ impl Error for AllocError {}
4343
// (we need this for downstream impl of trait Error)
4444
#[unstable(feature = "allocator_api", issue = "32838")]
4545
impl fmt::Display for AllocError {
46+
#[inline]
4647
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
4748
f.write_str("memory allocation failed")
4849
}

library/core/src/any.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -630,6 +630,7 @@ impl TypeId {
630630
#[must_use]
631631
#[stable(feature = "rust1", since = "1.0.0")]
632632
#[rustc_const_unstable(feature = "const_type_id", issue = "77125")]
633+
#[inline]
633634
pub const fn of<T: ?Sized + 'static>() -> TypeId {
634635
let t: u128 = intrinsics::type_id::<T>();
635636
TypeId { t }

library/core/src/ascii.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ pub struct EscapeDefault(escape::EscapeIterInner<4>);
9090
/// assert_eq!(b'd', escaped.next().unwrap());
9191
/// ```
9292
#[stable(feature = "rust1", since = "1.0.0")]
93+
#[inline]
9394
pub fn escape_default(c: u8) -> EscapeDefault {
9495
let mut data = [Char::Null; 4];
9596
let range = escape::escape_ascii_into(&mut data, c);

library/core/src/ascii/ascii_char.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -559,6 +559,7 @@ impl [AsciiChar] {
559559

560560
#[unstable(feature = "ascii_char", issue = "110998")]
561561
impl fmt::Display for AsciiChar {
562+
#[inline]
562563
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
563564
<str as fmt::Display>::fmt(self.as_str(), f)
564565
}

library/core/src/cell.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -722,6 +722,7 @@ impl Debug for BorrowError {
722722

723723
#[stable(feature = "try_borrow", since = "1.13.0")]
724724
impl Display for BorrowError {
725+
#[inline]
725726
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
726727
Display::fmt("already mutably borrowed", f)
727728
}
@@ -749,6 +750,7 @@ impl Debug for BorrowMutError {
749750

750751
#[stable(feature = "try_borrow", since = "1.13.0")]
751752
impl Display for BorrowMutError {
753+
#[inline]
752754
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
753755
Display::fmt("already borrowed", f)
754756
}

0 commit comments

Comments
 (0)