Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add #[inline] to small functions in core #116583

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions compiler/rustc_mir_transform/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ mir_transform_requires_unsafe = {$details} is unsafe and requires unsafe {$op_in
}
.not_inherited = items do not inherit unsafety from separate enclosing items

mir_transform_small_fn_without_inline = this function looks small ({$statements}) but doesn't have #[inline], consider adding it
.suggestion = add the inline attribute

mir_transform_target_feature_call_label = call to function with `#[target_feature]`
mir_transform_target_feature_call_note = can only be called if the required target features are available

Expand Down
39 changes: 34 additions & 5 deletions compiler/rustc_mir_transform/src/cross_crate_inline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,36 @@ fn cross_crate_inlinable(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
};

let mir = tcx.optimized_mir(def_id);
let mut checker =
CostChecker { tcx, callee_body: mir, calls: 0, statements: 0, landing_pads: 0, resumes: 0 };
let mut checker = CostChecker {
tcx,
callee_body: mir,
calls: 0,
statements: 0,
landing_pads: 0,
resumes: 0,
branches: 0,
asserts: 0,
};
checker.visit_body(mir);
checker.calls == 0
let is_leaf = checker.calls == 0
&& checker.resumes == 0
&& checker.landing_pads == 0
&& checker.statements <= threshold
&& checker.statements <= threshold;

let is_trivial_wrapper = checker.calls == 1
&& checker.resumes == 0
&& checker.landing_pads == 0
&& mir.basic_blocks.len() == 2;

if is_trivial_wrapper {
let span = tcx.def_span(def_id);
tcx.sess.emit_warning(crate::errors::SuggestAddingInline {
place: span,
suggest_inline: span.with_hi(span.lo()),
statements: checker.statements,
});
}
is_leaf
}

struct CostChecker<'b, 'tcx> {
Expand All @@ -78,6 +101,8 @@ struct CostChecker<'b, 'tcx> {
statements: usize,
landing_pads: usize,
resumes: usize,
branches: usize,
asserts: usize,
}

impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> {
Expand Down Expand Up @@ -111,7 +136,7 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> {
}
}
TerminatorKind::Assert { unwind, .. } => {
self.calls += 1;
self.asserts += 1;
if let UnwindAction::Cleanup(_) = unwind {
self.landing_pads += 1;
}
Expand All @@ -123,6 +148,10 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> {
self.landing_pads += 1;
}
}
TerminatorKind::SwitchInt { .. } => {
self.statements += 1;
self.branches += 1;
}
TerminatorKind::Return => {}
_ => self.statements += 1,
}
Expand Down
10 changes: 10 additions & 0 deletions compiler/rustc_mir_transform/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -278,3 +278,13 @@ pub(crate) struct MustNotSuspendReason {
pub span: Span,
pub reason: String,
}

#[derive(Diagnostic)]
#[diag(mir_transform_small_fn_without_inline)]
pub struct SuggestAddingInline {
#[primary_span]
pub place: Span,
#[suggestion(code = "#[inline]\n", applicability = "machine-applicable")]
pub suggest_inline: Span,
pub statements: usize,
}
1 change: 1 addition & 0 deletions library/core/src/alloc/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,7 @@ impl Error for LayoutError {}
// (we need this for downstream impl of trait Error)
#[stable(feature = "alloc_layout", since = "1.28.0")]
impl fmt::Display for LayoutError {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("invalid parameters to Layout::from_size_align")
}
Expand Down
1 change: 1 addition & 0 deletions library/core/src/alloc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ impl Error for AllocError {}
// (we need this for downstream impl of trait Error)
#[unstable(feature = "allocator_api", issue = "32838")]
impl fmt::Display for AllocError {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("memory allocation failed")
}
Expand Down
1 change: 1 addition & 0 deletions library/core/src/any.rs
Original file line number Diff line number Diff line change
Expand Up @@ -630,6 +630,7 @@ impl TypeId {
#[must_use]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_type_id", issue = "77125")]
#[inline]
pub const fn of<T: ?Sized + 'static>() -> TypeId {
let t: u128 = intrinsics::type_id::<T>();
TypeId { t }
Expand Down
1 change: 1 addition & 0 deletions library/core/src/array/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,7 @@ impl<'a, T, const N: usize> IntoIterator for &'a [T; N] {
type Item = &'a T;
type IntoIter = Iter<'a, T>;

#[inline]
fn into_iter(self) -> Iter<'a, T> {
self.iter()
}
Expand Down
1 change: 1 addition & 0 deletions library/core/src/ascii.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ pub struct EscapeDefault(escape::EscapeIterInner<4>);
/// assert_eq!(b'd', escaped.next().unwrap());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn escape_default(c: u8) -> EscapeDefault {
let mut data = [Char::Null; 4];
let range = escape::escape_ascii_into(&mut data, c);
Expand Down
1 change: 1 addition & 0 deletions library/core/src/ascii/ascii_char.rs
Original file line number Diff line number Diff line change
Expand Up @@ -559,6 +559,7 @@ impl [AsciiChar] {

#[unstable(feature = "ascii_char", issue = "110998")]
impl fmt::Display for AsciiChar {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
<str as fmt::Display>::fmt(self.as_str(), f)
}
Expand Down
2 changes: 2 additions & 0 deletions library/core/src/cell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -722,6 +722,7 @@ impl Debug for BorrowError {

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

#[stable(feature = "try_borrow", since = "1.13.0")]
impl Display for BorrowMutError {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Display::fmt("already borrowed", f)
}
Expand Down
1 change: 1 addition & 0 deletions library/core/src/char/convert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,7 @@ pub struct CharTryFromError(());

#[stable(feature = "try_from", since = "1.34.0")]
impl fmt::Display for CharTryFromError {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
"converted integer out of range for `char`".fmt(f)
}
Expand Down
12 changes: 12 additions & 0 deletions library/core/src/char/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ pub const fn from_digit(num: u32, radix: u32) -> Option<char> {
pub struct EscapeUnicode(escape::EscapeIterInner<10>);

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

impl EscapeDefault {
#[inline]
fn printable(chr: ascii::Char) -> Self {
let data = [chr];
Self(escape::EscapeIterInner::from_array(data))
}

#[inline]
fn backslash(chr: ascii::Char) -> Self {
let data = [ascii::Char::ReverseSolidus, chr];
Self(escape::EscapeIterInner::from_array(data))
Expand Down Expand Up @@ -308,6 +311,7 @@ impl EscapeDebug {
Self(EscapeDebugInner::Char(chr))
}

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

#[inline]
fn clear(&mut self) {
let bytes = escape::EscapeIterInner::from_array([]);
self.0 = EscapeDebugInner::Bytes(bytes);
Expand Down Expand Up @@ -386,6 +391,7 @@ pub struct ToLowercase(CaseMappingIter);
#[stable(feature = "rust1", since = "1.0.0")]
impl Iterator for ToLowercase {
type Item = char;
#[inline]
fn next(&mut self) -> Option<char> {
self.0.next()
}
Expand All @@ -396,6 +402,7 @@ impl Iterator for ToLowercase {

#[stable(feature = "case_mapping_double_ended", since = "1.59.0")]
impl DoubleEndedIterator for ToLowercase {
#[inline]
fn next_back(&mut self) -> Option<char> {
self.0.next_back()
}
Expand All @@ -420,6 +427,7 @@ pub struct ToUppercase(CaseMappingIter);
#[stable(feature = "rust1", since = "1.0.0")]
impl Iterator for ToUppercase {
type Item = char;
#[inline]
fn next(&mut self) -> Option<char> {
self.0.next()
}
Expand All @@ -430,6 +438,7 @@ impl Iterator for ToUppercase {

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

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

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

#[stable(feature = "u8_from_char", since = "1.59.0")]
impl fmt::Display for TryFromCharError {
#[inline]
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
"unicode code point out of range".fmt(fmt)
}
Expand Down
2 changes: 2 additions & 0 deletions library/core/src/escape.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,12 @@ impl<const N: usize> EscapeIterInner<N> {
Self::new(data, 0..M as u8)
}

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

#[inline]
pub fn as_str(&self) -> &str {
self.as_ascii().as_str()
}
Expand Down
2 changes: 2 additions & 0 deletions library/core/src/ffi/c_str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ pub struct FromBytesUntilNulError(());

#[stable(feature = "cstr_from_bytes_until_nul", since = "1.69.0")]
impl fmt::Display for FromBytesUntilNulError {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "data provided does not contain a nul")
}
Expand Down Expand Up @@ -623,6 +624,7 @@ impl CStr {
/// ```
#[stable(feature = "cstr_to_str", since = "1.4.0")]
#[rustc_const_stable(feature = "const_cstr_methods", since = "1.72.0")]
#[inline]
pub const fn to_str(&self) -> Result<&str, str::Utf8Error> {
// N.B., when `CStr` is changed to perform the length check in `.to_bytes()`
// instead of in `from_ptr()`, it may be worth considering if this should
Expand Down
12 changes: 12 additions & 0 deletions library/core/src/fmt/builders.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ impl Default for PadAdapterState {
}

impl<'buf, 'state> PadAdapter<'buf, 'state> {
#[inline]
fn wrap<'slot, 'fmt: 'buf + 'slot>(
fmt: &'fmt mut fmt::Formatter<'_>,
slot: &'slot mut Option<Self>,
Expand Down Expand Up @@ -91,6 +92,7 @@ pub struct DebugStruct<'a, 'b: 'a> {
has_fields: bool,
}

#[inline]
pub(super) fn debug_struct_new<'a, 'b>(
fmt: &'a mut fmt::Formatter<'b>,
name: &str,
Expand Down Expand Up @@ -138,6 +140,7 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> {
/// This method is equivalent to [`DebugStruct::field`], but formats the
/// value using a provided closure rather than by calling [`Debug::fmt`].
#[unstable(feature = "debug_closure_helpers", issue = "117729")]
#[inline]
pub fn field_with<F>(&mut self, name: &str, value_fmt: F) -> &mut Self
where
F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result,
Expand Down Expand Up @@ -293,6 +296,7 @@ pub struct DebugTuple<'a, 'b: 'a> {
empty_name: bool,
}

#[inline]
pub(super) fn debug_tuple_new<'a, 'b>(
fmt: &'a mut fmt::Formatter<'b>,
name: &str,
Expand Down Expand Up @@ -326,6 +330,7 @@ impl<'a, 'b: 'a> DebugTuple<'a, 'b> {
/// );
/// ```
#[stable(feature = "debug_builders", since = "1.2.0")]
#[inline]
pub fn field(&mut self, value: &dyn fmt::Debug) -> &mut Self {
self.field_with(|f| value.fmt(f))
}
Expand All @@ -335,6 +340,7 @@ impl<'a, 'b: 'a> DebugTuple<'a, 'b> {
/// This method is equivalent to [`DebugTuple::field`], but formats the
/// value using a provided closure rather than by calling [`Debug::fmt`].
#[unstable(feature = "debug_closure_helpers", issue = "117729")]
#[inline]
pub fn field_with<F>(&mut self, value_fmt: F) -> &mut Self
where
F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result,
Expand Down Expand Up @@ -409,6 +415,7 @@ struct DebugInner<'a, 'b: 'a> {
}

impl<'a, 'b: 'a> DebugInner<'a, 'b> {
#[inline]
fn entry_with<F>(&mut self, entry_fmt: F)
where
F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result,
Expand Down Expand Up @@ -471,6 +478,7 @@ pub struct DebugSet<'a, 'b: 'a> {
inner: DebugInner<'a, 'b>,
}

#[inline]
pub(super) fn debug_set_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugSet<'a, 'b> {
let result = fmt.write_str("{");
DebugSet { inner: DebugInner { fmt, result, has_fields: false } }
Expand Down Expand Up @@ -614,6 +622,7 @@ pub struct DebugList<'a, 'b: 'a> {
inner: DebugInner<'a, 'b>,
}

#[inline]
pub(super) fn debug_list_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugList<'a, 'b> {
let result = fmt.write_str("[");
DebugList { inner: DebugInner { fmt, result, has_fields: false } }
Expand Down Expand Up @@ -762,6 +771,7 @@ pub struct DebugMap<'a, 'b: 'a> {
state: PadAdapterState,
}

#[inline]
pub(super) fn debug_map_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugMap<'a, 'b> {
let result = fmt.write_str("{");
DebugMap { fmt, result, has_fields: false, has_key: false, state: Default::default() }
Expand Down Expand Up @@ -836,6 +846,7 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> {
/// This method is equivalent to [`DebugMap::key`], but formats the
/// key using a provided closure rather than by calling [`Debug::fmt`].
#[unstable(feature = "debug_closure_helpers", issue = "117729")]
#[inline]
pub fn key_with<F>(&mut self, key_fmt: F) -> &mut Self
where
F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result,
Expand Down Expand Up @@ -912,6 +923,7 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> {
/// This method is equivalent to [`DebugMap::value`], but formats the
/// value using a provided closure rather than by calling [`Debug::fmt`].
#[unstable(feature = "debug_closure_helpers", issue = "117729")]
#[inline]
pub fn value_with<F>(&mut self, value_fmt: F) -> &mut Self
where
F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result,
Expand Down
Loading
Loading