Skip to content

Commit d11ea83

Browse files
committed
Auto merge of #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 f81d6f0 + 9c3c8ef commit d11ea83

40 files changed

+162
-6
lines changed

compiler/rustc_builtin_macros/src/deriving/debug.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ pub fn expand_deriving_debug(
3333
explicit_self: true,
3434
nonself_args: vec![(fmtr, sym::f)],
3535
ret_ty: Path(path_std!(fmt::Result)),
36-
attributes: ast::AttrVec::new(),
36+
attributes: thin_vec![cx.attr_word(sym::inline, span)],
3737
fieldless_variants_strategy:
3838
FieldlessVariantsStrategy::SpecializeIfAllVariantsFieldless,
3939
combine_substructure: combine_substructure(Box::new(|a, b, c| {

compiler/rustc_mir_transform/messages.ftl

+3
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

+34-5
Original file line numberDiff line numberDiff line change
@@ -55,14 +55,37 @@ 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+
tcx.sess.emit_warning(crate::errors::SuggestAddingInline {
83+
place: span,
84+
suggest_inline: span.with_hi(span.lo()),
85+
statements: checker.statements,
86+
});
87+
}
88+
is_leaf
6689
}
6790

6891
struct CostChecker<'b, 'tcx> {
@@ -72,6 +95,8 @@ struct CostChecker<'b, 'tcx> {
7295
statements: usize,
7396
landing_pads: usize,
7497
resumes: usize,
98+
branches: usize,
99+
asserts: usize,
75100
}
76101

77102
impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> {
@@ -105,7 +130,7 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> {
105130
}
106131
}
107132
TerminatorKind::Assert { unwind, .. } => {
108-
self.calls += 1;
133+
self.asserts += 1;
109134
if let UnwindAction::Cleanup(_) = unwind {
110135
self.landing_pads += 1;
111136
}
@@ -117,6 +142,10 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> {
117142
self.landing_pads += 1;
118143
}
119144
}
145+
TerminatorKind::SwitchInt { .. } => {
146+
self.statements += 1;
147+
self.branches += 1;
148+
}
120149
TerminatorKind::Return => {}
121150
_ => self.statements += 1,
122151
}

compiler/rustc_mir_transform/src/errors.rs

+10
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

+1
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

+1
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

+1
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

+1
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

+1
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

+2
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
}

library/core/src/char/convert.rs

+1
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,7 @@ pub struct CharTryFromError(());
264264

265265
#[stable(feature = "try_from", since = "1.34.0")]
266266
impl fmt::Display for CharTryFromError {
267+
#[inline]
267268
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
268269
"converted integer out of range for `char`".fmt(f)
269270
}

library/core/src/char/mod.rs

+12
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ pub const fn from_digit(num: u32, radix: u32) -> Option<char> {
152152
pub struct EscapeUnicode(escape::EscapeIterInner<10>);
153153

154154
impl EscapeUnicode {
155+
#[inline]
155156
fn new(chr: char) -> Self {
156157
let mut data = [ascii::Char::Null; 10];
157158
let range = escape::escape_unicode_into(&mut data, chr);
@@ -219,11 +220,13 @@ impl fmt::Display for EscapeUnicode {
219220
pub struct EscapeDefault(escape::EscapeIterInner<10>);
220221

221222
impl EscapeDefault {
223+
#[inline]
222224
fn printable(chr: ascii::Char) -> Self {
223225
let data = [chr];
224226
Self(escape::EscapeIterInner::from_array(data))
225227
}
226228

229+
#[inline]
227230
fn backslash(chr: ascii::Char) -> Self {
228231
let data = [ascii::Char::ReverseSolidus, chr];
229232
Self(escape::EscapeIterInner::from_array(data))
@@ -308,6 +311,7 @@ impl EscapeDebug {
308311
Self(EscapeDebugInner::Char(chr))
309312
}
310313

314+
#[inline]
311315
fn backslash(chr: ascii::Char) -> Self {
312316
let data = [ascii::Char::ReverseSolidus, chr];
313317
let iter = escape::EscapeIterInner::from_array(data);
@@ -318,6 +322,7 @@ impl EscapeDebug {
318322
Self(EscapeDebugInner::Bytes(esc.0))
319323
}
320324

325+
#[inline]
321326
fn clear(&mut self) {
322327
let bytes = escape::EscapeIterInner::from_array([]);
323328
self.0 = EscapeDebugInner::Bytes(bytes);
@@ -386,6 +391,7 @@ pub struct ToLowercase(CaseMappingIter);
386391
#[stable(feature = "rust1", since = "1.0.0")]
387392
impl Iterator for ToLowercase {
388393
type Item = char;
394+
#[inline]
389395
fn next(&mut self) -> Option<char> {
390396
self.0.next()
391397
}
@@ -396,6 +402,7 @@ impl Iterator for ToLowercase {
396402

397403
#[stable(feature = "case_mapping_double_ended", since = "1.59.0")]
398404
impl DoubleEndedIterator for ToLowercase {
405+
#[inline]
399406
fn next_back(&mut self) -> Option<char> {
400407
self.0.next_back()
401408
}
@@ -420,6 +427,7 @@ pub struct ToUppercase(CaseMappingIter);
420427
#[stable(feature = "rust1", since = "1.0.0")]
421428
impl Iterator for ToUppercase {
422429
type Item = char;
430+
#[inline]
423431
fn next(&mut self) -> Option<char> {
424432
self.0.next()
425433
}
@@ -430,6 +438,7 @@ impl Iterator for ToUppercase {
430438

431439
#[stable(feature = "case_mapping_double_ended", since = "1.59.0")]
432440
impl DoubleEndedIterator for ToUppercase {
441+
#[inline]
433442
fn next_back(&mut self) -> Option<char> {
434443
self.0.next_back()
435444
}
@@ -534,13 +543,15 @@ impl fmt::Display for CaseMappingIter {
534543

535544
#[stable(feature = "char_struct_display", since = "1.16.0")]
536545
impl fmt::Display for ToLowercase {
546+
#[inline]
537547
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
538548
fmt::Display::fmt(&self.0, f)
539549
}
540550
}
541551

542552
#[stable(feature = "char_struct_display", since = "1.16.0")]
543553
impl fmt::Display for ToUppercase {
554+
#[inline]
544555
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
545556
fmt::Display::fmt(&self.0, f)
546557
}
@@ -553,6 +564,7 @@ pub struct TryFromCharError(pub(crate) ());
553564

554565
#[stable(feature = "u8_from_char", since = "1.59.0")]
555566
impl fmt::Display for TryFromCharError {
567+
#[inline]
556568
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
557569
"unicode code point out of range".fmt(fmt)
558570
}

library/core/src/escape.rs

+2
Original file line numberDiff line numberDiff line change
@@ -82,10 +82,12 @@ impl<const N: usize> EscapeIterInner<N> {
8282
Self::new(data, 0..M as u8)
8383
}
8484

85+
#[inline]
8586
pub fn as_ascii(&self) -> &[ascii::Char] {
8687
&self.data[usize::from(self.alive.start)..usize::from(self.alive.end)]
8788
}
8889

90+
#[inline]
8991
pub fn as_str(&self) -> &str {
9092
self.as_ascii().as_str()
9193
}

library/core/src/ffi/c_str.rs

+2
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ pub struct FromBytesUntilNulError(());
158158

159159
#[stable(feature = "cstr_from_bytes_until_nul", since = "1.69.0")]
160160
impl fmt::Display for FromBytesUntilNulError {
161+
#[inline]
161162
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
162163
write!(f, "data provided does not contain a nul")
163164
}
@@ -623,6 +624,7 @@ impl CStr {
623624
/// ```
624625
#[stable(feature = "cstr_to_str", since = "1.4.0")]
625626
#[rustc_const_stable(feature = "const_cstr_methods", since = "1.72.0")]
627+
#[inline]
626628
pub const fn to_str(&self) -> Result<&str, str::Utf8Error> {
627629
// N.B., when `CStr` is changed to perform the length check in `.to_bytes()`
628630
// instead of in `from_ptr()`, it may be worth considering if this should

library/core/src/fmt/builders.rs

+8
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ impl Default for PadAdapterState {
1818
}
1919

2020
impl<'buf, 'state> PadAdapter<'buf, 'state> {
21+
#[inline]
2122
fn wrap<'slot, 'fmt: 'buf + 'slot>(
2223
fmt: &'fmt mut fmt::Formatter<'_>,
2324
slot: &'slot mut Option<Self>,
@@ -91,6 +92,7 @@ pub struct DebugStruct<'a, 'b: 'a> {
9192
has_fields: bool,
9293
}
9394

95+
#[inline]
9496
pub(super) fn debug_struct_new<'a, 'b>(
9597
fmt: &'a mut fmt::Formatter<'b>,
9698
name: &str,
@@ -281,6 +283,7 @@ pub struct DebugTuple<'a, 'b: 'a> {
281283
empty_name: bool,
282284
}
283285

286+
#[inline]
284287
pub(super) fn debug_tuple_new<'a, 'b>(
285288
fmt: &'a mut fmt::Formatter<'b>,
286289
name: &str,
@@ -444,6 +447,7 @@ pub struct DebugSet<'a, 'b: 'a> {
444447
inner: DebugInner<'a, 'b>,
445448
}
446449

450+
#[inline]
447451
pub(super) fn debug_set_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugSet<'a, 'b> {
448452
let result = fmt.write_str("{");
449453
DebugSet { inner: DebugInner { fmt, result, has_fields: false } }
@@ -474,6 +478,7 @@ impl<'a, 'b: 'a> DebugSet<'a, 'b> {
474478
/// );
475479
/// ```
476480
#[stable(feature = "debug_builders", since = "1.2.0")]
481+
#[inline]
477482
pub fn entry(&mut self, entry: &dyn fmt::Debug) -> &mut Self {
478483
self.inner.entry(entry);
479484
self
@@ -574,6 +579,7 @@ pub struct DebugList<'a, 'b: 'a> {
574579
inner: DebugInner<'a, 'b>,
575580
}
576581

582+
#[inline]
577583
pub(super) fn debug_list_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugList<'a, 'b> {
578584
let result = fmt.write_str("[");
579585
DebugList { inner: DebugInner { fmt, result, has_fields: false } }
@@ -604,6 +610,7 @@ impl<'a, 'b: 'a> DebugList<'a, 'b> {
604610
/// );
605611
/// ```
606612
#[stable(feature = "debug_builders", since = "1.2.0")]
613+
#[inline]
607614
pub fn entry(&mut self, entry: &dyn fmt::Debug) -> &mut Self {
608615
self.inner.entry(entry);
609616
self
@@ -709,6 +716,7 @@ pub struct DebugMap<'a, 'b: 'a> {
709716
state: PadAdapterState,
710717
}
711718

719+
#[inline]
712720
pub(super) fn debug_map_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugMap<'a, 'b> {
713721
let result = fmt.write_str("{");
714722
DebugMap { fmt, result, has_fields: false, has_key: false, state: Default::default() }

library/core/src/fmt/float.rs

+4
Original file line numberDiff line numberDiff line change
@@ -198,27 +198,31 @@ macro_rules! floating {
198198
($ty:ident) => {
199199
#[stable(feature = "rust1", since = "1.0.0")]
200200
impl Debug for $ty {
201+
#[inline]
201202
fn fmt(&self, fmt: &mut Formatter<'_>) -> Result {
202203
float_to_general_debug(fmt, self)
203204
}
204205
}
205206

206207
#[stable(feature = "rust1", since = "1.0.0")]
207208
impl Display for $ty {
209+
#[inline]
208210
fn fmt(&self, fmt: &mut Formatter<'_>) -> Result {
209211
float_to_decimal_display(fmt, self)
210212
}
211213
}
212214

213215
#[stable(feature = "rust1", since = "1.0.0")]
214216
impl LowerExp for $ty {
217+
#[inline]
215218
fn fmt(&self, fmt: &mut Formatter<'_>) -> Result {
216219
float_to_exponential_common(fmt, self, false)
217220
}
218221
}
219222

220223
#[stable(feature = "rust1", since = "1.0.0")]
221224
impl UpperExp for $ty {
225+
#[inline]
222226
fn fmt(&self, fmt: &mut Formatter<'_>) -> Result {
223227
float_to_exponential_common(fmt, self, true)
224228
}

0 commit comments

Comments
 (0)