Skip to content

Commit 7c9c7ed

Browse files
authored
Rollup merge of #149763 - aerooneqq:add-inline-attribute, r=petrochenkov
Add inline attribute to generated delegation function if needed This PR adds a functionality to add #[inline(always)] attribute to generated functions from delegation, if some #[inline(..)] attribute is already specified on the delegation then we do nothing. This PR is a part of the delegation feature #118212 and addresses `Add implicit #[inline] unless specified otherwise` item. r? ``@petrochenkov``
2 parents b13a253 + 8cf942d commit 7c9c7ed

File tree

4 files changed

+228
-0
lines changed

4 files changed

+228
-0
lines changed

compiler/rustc_ast_lowering/src/delegation.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ use hir::{BodyId, HirId};
4444
use rustc_abi::ExternAbi;
4545
use rustc_ast::*;
4646
use rustc_errors::ErrorGuaranteed;
47+
use rustc_hir::attrs::{AttributeKind, InlineAttr};
4748
use rustc_hir::def_id::DefId;
4849
use rustc_middle::span_bug;
4950
use rustc_middle::ty::{Asyncness, ResolverAstLowering};
@@ -87,6 +88,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
8788
let sig_id = self.get_delegation_sig_id(item_id, delegation.id, span, is_in_trait_impl);
8889
match sig_id {
8990
Ok(sig_id) => {
91+
self.add_inline_attribute_if_needed(span);
92+
9093
let is_method = self.is_method(sig_id, span);
9194
let (param_count, c_variadic) = self.param_count(sig_id);
9295
let decl = self.lower_delegation_decl(sig_id, param_count, c_variadic, span);
@@ -100,6 +103,31 @@ impl<'hir> LoweringContext<'_, 'hir> {
100103
}
101104
}
102105

106+
fn add_inline_attribute_if_needed(&mut self, span: Span) {
107+
const PARENT_ID: hir::ItemLocalId = hir::ItemLocalId::ZERO;
108+
let create_inline_attr_slice =
109+
|| [hir::Attribute::Parsed(AttributeKind::Inline(InlineAttr::Hint, span))];
110+
111+
let new_attributes = match self.attrs.get(&PARENT_ID) {
112+
Some(attrs) => {
113+
// Check if reuse already specifies any inline attribute, if so, do nothing
114+
if attrs
115+
.iter()
116+
.any(|a| matches!(a, hir::Attribute::Parsed(AttributeKind::Inline(..))))
117+
{
118+
return;
119+
}
120+
121+
self.arena.alloc_from_iter(
122+
attrs.into_iter().map(|a| a.clone()).chain(create_inline_attr_slice()),
123+
)
124+
}
125+
None => self.arena.alloc_from_iter(create_inline_attr_slice()),
126+
};
127+
128+
self.attrs.insert(PARENT_ID, new_attributes);
129+
}
130+
103131
fn get_delegation_sig_id(
104132
&self,
105133
item_id: NodeId,
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
//@ pretty-compare-only
2+
//@ pretty-mode:hir
3+
//@ pp-exact:delegation_inline_attribute.pp
4+
5+
#![allow(incomplete_features)]
6+
#![feature(fn_delegation)]
7+
#[attr = MacroUse {arguments: UseAll}]
8+
extern crate std;
9+
#[prelude_import]
10+
use ::std::prelude::rust_2015::*;
11+
12+
mod to_reuse {
13+
fn foo(x: usize) -> usize { x }
14+
}
15+
16+
// Check that #[inline(hint)] is added to foo reuse
17+
#[attr = Inline(Hint)]
18+
fn bar(arg0: _) -> _ { to_reuse::foo(self + 1) }
19+
20+
trait Trait {
21+
fn foo(&self) { }
22+
fn foo1(&self) { }
23+
fn foo2(&self) { }
24+
fn foo3(&self) { }
25+
fn foo4(&self) { }
26+
}
27+
28+
impl Trait for u8 { }
29+
30+
struct S(u8);
31+
32+
mod to_import {
33+
fn check(arg: &'_ u8) -> &'_ u8 { arg }
34+
}
35+
36+
impl Trait for S {
37+
// Check that #[inline(hint)] is added to foo reuse
38+
#[attr = Inline(Hint)]
39+
fn foo(self: _)
40+
->
41+
_ {
42+
{
43+
// Check that #[inline(hint)] is added to foo0 reuse inside another reuse
44+
#[attr = Inline(Hint)]
45+
fn foo0(arg0: _) -> _ { to_reuse::foo(self + 1) }
46+
47+
// Check that #[inline(hint)] is added when other attributes present in inner reuse
48+
#[attr = Deprecation {deprecation: Deprecation {since: Unspecified}}]
49+
#[attr = MustUse]
50+
#[attr = Cold]
51+
#[attr = Inline(Hint)]
52+
fn foo1(arg0: _) -> _ { to_reuse::foo(self / 2) }
53+
54+
// Check that #[inline(never)] is preserved in inner reuse
55+
#[attr = Inline(Never)]
56+
fn foo2(arg0: _) -> _ { to_reuse::foo(self / 2) }
57+
58+
// Check that #[inline(always)] is preserved in inner reuse
59+
#[attr = Inline(Always)]
60+
fn foo3(arg0: _) -> _ { to_reuse::foo(self / 2) }
61+
62+
// Check that #[inline(never)] is preserved when there are other attributes in inner reuse
63+
#[attr = Deprecation {deprecation: Deprecation {since: Unspecified}}]
64+
#[attr = Inline(Never)]
65+
#[attr = MustUse]
66+
#[attr = Cold]
67+
fn foo4(arg0: _) -> _ { to_reuse::foo(self / 2) }
68+
}.foo()
69+
}
70+
71+
// Check that #[inline(hint)] is added when there are other attributes present in trait reuse
72+
#[attr = Deprecation {deprecation: Deprecation {since: Unspecified}}]
73+
#[attr = MustUse]
74+
#[attr = Cold]
75+
#[attr = Inline(Hint)]
76+
fn foo1(self: _) -> _ { self.0.foo1() }
77+
78+
// Check that #[inline(never)] is preserved in trait reuse
79+
#[attr = Inline(Never)]
80+
fn foo2(self: _) -> _ { self.0.foo2() }
81+
82+
// Check that #[inline(always)] is preserved in trait reuse
83+
#[attr = Inline(Always)]
84+
fn foo3(self: _) -> _ { self.0.foo3() }
85+
86+
// Check that #[inline(never)] is preserved when there are other attributes in trait reuse
87+
#[attr = Deprecation {deprecation: Deprecation {since: Unspecified}}]
88+
#[attr = Inline(Never)]
89+
#[attr = MustUse]
90+
#[attr = Cold]
91+
fn foo4(self: _) -> _ { self.0.foo4() }
92+
}
93+
94+
fn main() { }
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
//@ pretty-compare-only
2+
//@ pretty-mode:hir
3+
//@ pp-exact:delegation_inline_attribute.pp
4+
5+
#![allow(incomplete_features)]
6+
#![feature(fn_delegation)]
7+
8+
mod to_reuse {
9+
pub fn foo(x: usize) -> usize {
10+
x
11+
}
12+
}
13+
14+
// Check that #[inline(hint)] is added to foo reuse
15+
reuse to_reuse::foo as bar {
16+
self + 1
17+
}
18+
19+
trait Trait {
20+
fn foo(&self) {}
21+
fn foo1(&self) {}
22+
fn foo2(&self) {}
23+
fn foo3(&self) {}
24+
fn foo4(&self) {}
25+
}
26+
27+
impl Trait for u8 {}
28+
29+
struct S(u8);
30+
31+
mod to_import {
32+
pub fn check(arg: &u8) -> &u8 { arg }
33+
}
34+
35+
impl Trait for S {
36+
// Check that #[inline(hint)] is added to foo reuse
37+
reuse Trait::foo {
38+
// Check that #[inline(hint)] is added to foo0 reuse inside another reuse
39+
reuse to_reuse::foo as foo0 {
40+
self + 1
41+
}
42+
43+
// Check that #[inline(hint)] is added when other attributes present in inner reuse
44+
#[cold]
45+
#[must_use]
46+
#[deprecated]
47+
reuse to_reuse::foo as foo1 {
48+
self / 2
49+
}
50+
51+
// Check that #[inline(never)] is preserved in inner reuse
52+
#[inline(never)]
53+
reuse to_reuse::foo as foo2 {
54+
self / 2
55+
}
56+
57+
// Check that #[inline(always)] is preserved in inner reuse
58+
#[inline(always)]
59+
reuse to_reuse::foo as foo3 {
60+
self / 2
61+
}
62+
63+
// Check that #[inline(never)] is preserved when there are other attributes in inner reuse
64+
#[cold]
65+
#[must_use]
66+
#[inline(never)]
67+
#[deprecated]
68+
reuse to_reuse::foo as foo4 {
69+
self / 2
70+
}
71+
}
72+
73+
// Check that #[inline(hint)] is added when there are other attributes present in trait reuse
74+
#[cold]
75+
#[must_use]
76+
#[deprecated]
77+
reuse Trait::foo1 {
78+
self.0
79+
}
80+
81+
// Check that #[inline(never)] is preserved in trait reuse
82+
#[inline(never)]
83+
reuse Trait::foo2 {
84+
self.0
85+
}
86+
87+
// Check that #[inline(always)] is preserved in trait reuse
88+
#[inline(always)]
89+
reuse Trait::foo3 {
90+
self.0
91+
}
92+
93+
// Check that #[inline(never)] is preserved when there are other attributes in trait reuse
94+
#[cold]
95+
#[must_use]
96+
#[inline(never)]
97+
#[deprecated]
98+
reuse Trait::foo4 {
99+
self.0
100+
}
101+
}
102+
103+
fn main() {
104+
}

tests/pretty/hir-delegation.pp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,15 @@
1212
fn b<C>(e: C) { }
1313

1414
trait G {
15+
#[attr = Inline(Hint)]
1516
fn b(arg0: _) -> _ { b({ }) }
1617
}
1718

1819
mod m {
1920
fn add(a: u32, b: u32) -> u32 { a + b }
2021
}
2122

23+
#[attr = Inline(Hint)]
2224
fn add(arg0: _, arg1: _) -> _ { m::add(arg0, arg1) }
2325

2426
fn main() { { let _ = add(1, 2); }; }

0 commit comments

Comments
 (0)