Skip to content

Commit 4f840a6

Browse files
committed
Add inline to TransFnAttrs
Part of #47320
1 parent e8cd6cc commit 4f840a6

File tree

13 files changed

+149
-137
lines changed

13 files changed

+149
-137
lines changed

src/librustc/hir/mod.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ use syntax::codemap::{self, Spanned};
3636
use syntax::abi::Abi;
3737
use syntax::ast::{self, Name, NodeId, DUMMY_NODE_ID, AsmDialect};
3838
use syntax::ast::{Attribute, Lit, StrStyle, FloatTy, IntTy, UintTy, MetaItem};
39+
use syntax::attr::InlineAttr;
3940
use syntax::ext::hygiene::SyntaxContext;
4041
use syntax::ptr::P;
4142
use syntax::symbol::{Symbol, keywords};
@@ -2214,6 +2215,7 @@ pub fn provide(providers: &mut Providers) {
22142215
#[derive(Clone, RustcEncodable, RustcDecodable, Hash)]
22152216
pub struct TransFnAttrs {
22162217
pub flags: TransFnAttrFlags,
2218+
pub inline: InlineAttr,
22172219
}
22182220

22192221
bitflags! {
@@ -2231,6 +2233,15 @@ impl TransFnAttrs {
22312233
pub fn new() -> TransFnAttrs {
22322234
TransFnAttrs {
22332235
flags: TransFnAttrFlags::empty(),
2236+
inline: InlineAttr::None,
2237+
}
2238+
}
2239+
2240+
/// True if `#[inline]` or `#[inline(always)]` is present.
2241+
pub fn requests_inline(&self) -> bool {
2242+
match self.inline {
2243+
InlineAttr::Hint | InlineAttr::Always => true,
2244+
InlineAttr::None | InlineAttr::Never => false,
22342245
}
22352246
}
22362247
}

src/librustc/ich/impls_hir.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use rustc_data_structures::stable_hasher::{HashStable, ToStableHashKey,
1919
StableHasher, StableHasherResult};
2020
use std::mem;
2121
use syntax::ast;
22+
use syntax::attr;
2223

2324
impl<'gcx> HashStable<StableHashingContext<'gcx>> for DefId {
2425
#[inline]
@@ -1145,9 +1146,11 @@ impl<'hir> HashStable<StableHashingContext<'hir>> for hir::TransFnAttrs
11451146
hasher: &mut StableHasher<W>) {
11461147
let hir::TransFnAttrs {
11471148
flags,
1149+
inline,
11481150
} = *self;
11491151

11501152
flags.hash_stable(hcx, hasher);
1153+
inline.hash_stable(hcx, hasher);
11511154
}
11521155
}
11531156

@@ -1160,6 +1163,14 @@ impl<'hir> HashStable<StableHashingContext<'hir>> for hir::TransFnAttrFlags
11601163
}
11611164
}
11621165

1166+
impl<'hir> HashStable<StableHashingContext<'hir>> for attr::InlineAttr {
1167+
fn hash_stable<W: StableHasherResult>(&self,
1168+
hcx: &mut StableHashingContext<'hir>,
1169+
hasher: &mut StableHasher<W>) {
1170+
mem::discriminant(self).hash_stable(hcx, hasher);
1171+
}
1172+
}
1173+
11631174
impl_stable_hash_for!(struct hir::Freevar {
11641175
def,
11651176
span

src/librustc/middle/reachable.rs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
// makes all other generics or inline functions that it references
1616
// reachable as well.
1717

18+
use hir::TransFnAttrs;
1819
use hir::map as hir_map;
1920
use hir::def::Def;
2021
use hir::def_id::{DefId, CrateNum};
@@ -43,8 +44,8 @@ fn generics_require_inlining(generics: &hir::Generics) -> bool {
4344
// Returns true if the given item must be inlined because it may be
4445
// monomorphized or it was marked with `#[inline]`. This will only return
4546
// true for functions.
46-
fn item_might_be_inlined(item: &hir::Item) -> bool {
47-
if attr::requests_inline(&item.attrs) {
47+
fn item_might_be_inlined(item: &hir::Item, attrs: TransFnAttrs) -> bool {
48+
if attrs.requests_inline() {
4849
return true
4950
}
5051

@@ -60,14 +61,15 @@ fn item_might_be_inlined(item: &hir::Item) -> bool {
6061
fn method_might_be_inlined<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
6162
impl_item: &hir::ImplItem,
6263
impl_src: DefId) -> bool {
63-
if attr::requests_inline(&impl_item.attrs) ||
64+
let trans_fn_attrs = tcx.trans_fn_attrs(impl_item.hir_id.owner_def_id());
65+
if trans_fn_attrs.requests_inline() ||
6466
generics_require_inlining(&impl_item.generics) {
6567
return true
6668
}
6769
if let Some(impl_node_id) = tcx.hir.as_local_node_id(impl_src) {
6870
match tcx.hir.find(impl_node_id) {
6971
Some(hir_map::NodeItem(item)) =>
70-
item_might_be_inlined(&item),
72+
item_might_be_inlined(&item, trans_fn_attrs),
7173
Some(..) | None =>
7274
span_bug!(impl_item.span, "impl did is not an item")
7375
}
@@ -160,7 +162,8 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
160162
match self.tcx.hir.find(node_id) {
161163
Some(hir_map::NodeItem(item)) => {
162164
match item.node {
163-
hir::ItemFn(..) => item_might_be_inlined(&item),
165+
hir::ItemFn(..) =>
166+
item_might_be_inlined(&item, self.tcx.trans_fn_attrs(def_id)),
164167
_ => false,
165168
}
166169
}
@@ -176,8 +179,9 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
176179
match impl_item.node {
177180
hir::ImplItemKind::Const(..) => true,
178181
hir::ImplItemKind::Method(..) => {
182+
let attrs = self.tcx.trans_fn_attrs(def_id);
179183
if generics_require_inlining(&impl_item.generics) ||
180-
attr::requests_inline(&impl_item.attrs) {
184+
attrs.requests_inline() {
181185
true
182186
} else {
183187
let impl_did = self.tcx
@@ -246,7 +250,8 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
246250
hir_map::NodeItem(item) => {
247251
match item.node {
248252
hir::ItemFn(.., body) => {
249-
if item_might_be_inlined(&item) {
253+
let def_id = self.tcx.hir.local_def_id(item.id);
254+
if item_might_be_inlined(&item, self.tcx.trans_fn_attrs(def_id)) {
250255
self.visit_nested_body(body);
251256
}
252257
}

src/librustc/ty/instance.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,6 @@ impl<'tcx> InstanceDef<'tcx> {
9696
&self,
9797
tcx: TyCtxt<'a, 'tcx, 'tcx>
9898
) -> bool {
99-
use syntax::attr::requests_inline;
10099
if self.is_inline(tcx) {
101100
return true
102101
}
@@ -106,8 +105,8 @@ impl<'tcx> InstanceDef<'tcx> {
106105
// available to normal end-users.
107106
return true
108107
}
109-
requests_inline(&self.attrs(tcx)[..]) ||
110-
tcx.is_const_fn(self.def_id())
108+
let trans_fn_attrs = tcx.trans_fn_attrs(self.def_id());
109+
trans_fn_attrs.requests_inline() || tcx.is_const_fn(self.def_id())
111110
}
112111
}
113112

src/librustc_metadata/encoder.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -832,7 +832,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
832832
} else if let hir::ImplItemKind::Method(ref sig, body) = ast_item.node {
833833
let generics = self.tcx.generics_of(def_id);
834834
let types = generics.parent_types as usize + generics.types.len();
835-
let needs_inline = types > 0 || attr::requests_inline(&ast_item.attrs);
835+
let needs_inline = types > 0 || tcx.trans_fn_attrs(def_id).requests_inline();
836836
let is_const_fn = sig.constness == hir::Constness::Const;
837837
let ast = if is_const_fn { Some(body) } else { None };
838838
let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir;
@@ -1123,7 +1123,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
11231123
hir::ItemConst(..) => self.encode_optimized_mir(def_id),
11241124
hir::ItemFn(_, _, constness, _, ref generics, _) => {
11251125
let has_tps = generics.ty_params().next().is_some();
1126-
let needs_inline = has_tps || attr::requests_inline(&item.attrs);
1126+
let needs_inline = has_tps || tcx.trans_fn_attrs(def_id).requests_inline();
11271127
let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir;
11281128
if needs_inline || constness == hir::Constness::Const || always_encode_mir {
11291129
self.encode_optimized_mir(def_id)

src/librustc_mir/monomorphize/item.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,8 +141,7 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug {
141141
// creating one copy of this `#[inline]` function which may
142142
// conflict with upstream crates as it could be an exported
143143
// symbol.
144-
let attrs = instance.def.attrs(tcx);
145-
match attr::find_inline_attr(Some(tcx.sess.diagnostic()), &attrs) {
144+
match tcx.trans_fn_attrs(instance.def_id()).inline {
146145
InlineAttr::Always => InstantiationMode::LocalCopy,
147146
_ => {
148147
InstantiationMode::GloballyShared { may_conflict: true }

src/librustc_mir/transform/inline.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
207207
}
208208

209209
let attrs = tcx.get_attrs(callsite.callee);
210-
let hint = attr::find_inline_attr(None, &attrs[..]);
210+
let hint = tcx.trans_fn_attrs(callsite.callee).inline;
211211

212212
let hinted = match hint {
213213
// Just treat inline(always) as a hint for now,

src/librustc_trans/attributes.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -103,15 +103,13 @@ pub fn set_probestack(cx: &CodegenCx, llfn: ValueRef) {
103103
/// Composite function which sets LLVM attributes for function depending on its AST (#[attribute])
104104
/// attributes.
105105
pub fn from_fn_attrs(cx: &CodegenCx, llfn: ValueRef, id: DefId) {
106-
use syntax::attr::*;
107-
let attrs = cx.tcx.get_attrs(id);
108-
inline(llfn, find_inline_attr(Some(cx.sess().diagnostic()), &attrs));
106+
let trans_fn_attrs = cx.tcx.trans_fn_attrs(id);
107+
108+
inline(llfn, trans_fn_attrs.inline);
109109

110110
set_frame_pointer_elimination(cx, llfn);
111111
set_probestack(cx, llfn);
112112

113-
let trans_fn_attrs = cx.tcx.trans_fn_attrs(id);
114-
115113
if trans_fn_attrs.flags.contains(TransFnAttrFlags::COLD) {
116114
Attribute::Cold.apply_llfn(Function, llfn);
117115
}

src/librustc_trans_utils/trans_crate.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -236,9 +236,7 @@ impl TransCrate for MetadataOnlyTransCrate {
236236
let _ = tcx.export_name(def_id);
237237
let _ = tcx.contains_extern_indicator(def_id);
238238
let _ = inst.def.is_inline(tcx);
239-
let attrs = inst.def.attrs(tcx);
240-
let _ =
241-
::syntax::attr::find_inline_attr(Some(tcx.sess.diagnostic()), &attrs);
239+
let _ = tcx.trans_fn_attrs(def_id);
242240
}
243241
}
244242
_ => {}

src/librustc_typeck/collect.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ use util::nodemap::FxHashMap;
4141
use rustc_const_math::ConstInt;
4242

4343
use syntax::{abi, ast};
44+
use syntax::ast::MetaItemKind;
45+
use syntax::attr::{InlineAttr, list_contains_name, mark_used};
4446
use syntax::codemap::Spanned;
4547
use syntax::symbol::{Symbol, keywords};
4648
use syntax_pos::{Span, DUMMY_SP};
@@ -1742,6 +1744,39 @@ fn trans_fn_attrs<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefId) -> TransFnAt
17421744
} else if attr.check_name("naked") {
17431745
trans_fn_attrs.flags |= TransFnAttrFlags::NAKED;
17441746
} else if attr.check_name("inline") {
1747+
trans_fn_attrs.inline = attrs.iter().fold(InlineAttr::None, |ia, attr| {
1748+
if attr.path != "inline" {
1749+
return ia;
1750+
}
1751+
let meta = match attr.meta() {
1752+
Some(meta) => meta.node,
1753+
None => return ia,
1754+
};
1755+
match meta {
1756+
MetaItemKind::Word => {
1757+
mark_used(attr);
1758+
InlineAttr::Hint
1759+
}
1760+
MetaItemKind::List(ref items) => {
1761+
mark_used(attr);
1762+
if items.len() != 1 {
1763+
span_err!(tcx.sess.diagnostic(), attr.span, E0534,
1764+
"expected one argument");
1765+
InlineAttr::None
1766+
} else if list_contains_name(&items[..], "always") {
1767+
InlineAttr::Always
1768+
} else if list_contains_name(&items[..], "never") {
1769+
InlineAttr::Never
1770+
} else {
1771+
span_err!(tcx.sess.diagnostic(), items[0].span, E0535,
1772+
"invalid argument");
1773+
1774+
InlineAttr::None
1775+
}
1776+
}
1777+
_ => ia,
1778+
}
1779+
});
17451780
}
17461781
}
17471782

src/librustc_typeck/diagnostics.rs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3705,6 +3705,75 @@ match r {
37053705
```
37063706
"##,
37073707

3708+
E0534: r##"
3709+
The `inline` attribute was malformed.
3710+
3711+
Erroneous code example:
3712+
3713+
```ignore (compile_fail not working here; see Issue #43707)
3714+
#[inline()] // error: expected one argument
3715+
pub fn something() {}
3716+
3717+
fn main() {}
3718+
```
3719+
3720+
The parenthesized `inline` attribute requires the parameter to be specified:
3721+
3722+
```
3723+
#[inline(always)]
3724+
fn something() {}
3725+
```
3726+
3727+
or:
3728+
3729+
```
3730+
#[inline(never)]
3731+
fn something() {}
3732+
```
3733+
3734+
Alternatively, a paren-less version of the attribute may be used to hint the
3735+
compiler about inlining opportunity:
3736+
3737+
```
3738+
#[inline]
3739+
fn something() {}
3740+
```
3741+
3742+
For more information about the inline attribute, read:
3743+
https://doc.rust-lang.org/reference.html#inline-attributes
3744+
"##,
3745+
3746+
E0535: r##"
3747+
An unknown argument was given to the `inline` attribute.
3748+
3749+
Erroneous code example:
3750+
3751+
```ignore (compile_fail not working here; see Issue #43707)
3752+
#[inline(unknown)] // error: invalid argument
3753+
pub fn something() {}
3754+
3755+
fn main() {}
3756+
```
3757+
3758+
The `inline` attribute only supports two arguments:
3759+
3760+
* always
3761+
* never
3762+
3763+
All other arguments given to the `inline` attribute will return this error.
3764+
Example:
3765+
3766+
```
3767+
#[inline(never)] // ok!
3768+
pub fn something() {}
3769+
3770+
fn main() {}
3771+
```
3772+
3773+
For more information about the inline attribute, https:
3774+
read://doc.rust-lang.org/reference.html#inline-attributes
3775+
"##,
3776+
37083777
E0559: r##"
37093778
An unknown field was specified into an enum's structure variant.
37103779

0 commit comments

Comments
 (0)