diff options
| author | Wesley Wiser <wwiser@gmail.com> | 2018-01-30 22:39:23 -0500 |
|---|---|---|
| committer | Wesley Wiser <wwiser@gmail.com> | 2018-03-06 19:58:02 -0500 |
| commit | 4f840a683aebb40a4eec0285a49962dfbc8f425b (patch) | |
| tree | 42a46993b1e9c9ecd2658f41aa4cc29bbf3e012d /src | |
| parent | e8cd6cc23783a6a020d2c14f1a0f343a6267195d (diff) | |
| download | rust-4f840a683aebb40a4eec0285a49962dfbc8f425b.tar.gz rust-4f840a683aebb40a4eec0285a49962dfbc8f425b.zip | |
Add `inline` to `TransFnAttrs`
Part of #47320
Diffstat (limited to 'src')
| -rw-r--r-- | src/librustc/hir/mod.rs | 11 | ||||
| -rw-r--r-- | src/librustc/ich/impls_hir.rs | 11 | ||||
| -rw-r--r-- | src/librustc/middle/reachable.rs | 19 | ||||
| -rw-r--r-- | src/librustc/ty/instance.rs | 5 | ||||
| -rw-r--r-- | src/librustc_metadata/encoder.rs | 4 | ||||
| -rw-r--r-- | src/librustc_mir/monomorphize/item.rs | 3 | ||||
| -rw-r--r-- | src/librustc_mir/transform/inline.rs | 2 | ||||
| -rw-r--r-- | src/librustc_trans/attributes.rs | 8 | ||||
| -rw-r--r-- | src/librustc_trans_utils/trans_crate.rs | 4 | ||||
| -rw-r--r-- | src/librustc_typeck/collect.rs | 35 | ||||
| -rw-r--r-- | src/librustc_typeck/diagnostics.rs | 69 | ||||
| -rw-r--r-- | src/libsyntax/attr.rs | 46 | ||||
| -rw-r--r-- | src/libsyntax/diagnostic_list.rs | 69 |
13 files changed, 149 insertions, 137 deletions
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 5de341ef511..f997a57d5d7 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -36,6 +36,7 @@ use syntax::codemap::{self, Spanned}; use syntax::abi::Abi; use syntax::ast::{self, Name, NodeId, DUMMY_NODE_ID, AsmDialect}; use syntax::ast::{Attribute, Lit, StrStyle, FloatTy, IntTy, UintTy, MetaItem}; +use syntax::attr::InlineAttr; use syntax::ext::hygiene::SyntaxContext; use syntax::ptr::P; use syntax::symbol::{Symbol, keywords}; @@ -2214,6 +2215,7 @@ pub fn provide(providers: &mut Providers) { #[derive(Clone, RustcEncodable, RustcDecodable, Hash)] pub struct TransFnAttrs { pub flags: TransFnAttrFlags, + pub inline: InlineAttr, } bitflags! { @@ -2231,6 +2233,15 @@ impl TransFnAttrs { pub fn new() -> TransFnAttrs { TransFnAttrs { flags: TransFnAttrFlags::empty(), + inline: InlineAttr::None, + } + } + + /// True if `#[inline]` or `#[inline(always)]` is present. + pub fn requests_inline(&self) -> bool { + match self.inline { + InlineAttr::Hint | InlineAttr::Always => true, + InlineAttr::None | InlineAttr::Never => false, } } } diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs index d3151476fff..4720c0ca583 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -19,6 +19,7 @@ use rustc_data_structures::stable_hasher::{HashStable, ToStableHashKey, StableHasher, StableHasherResult}; use std::mem; use syntax::ast; +use syntax::attr; impl<'gcx> HashStable<StableHashingContext<'gcx>> for DefId { #[inline] @@ -1145,9 +1146,11 @@ impl<'hir> HashStable<StableHashingContext<'hir>> for hir::TransFnAttrs hasher: &mut StableHasher<W>) { let hir::TransFnAttrs { flags, + inline, } = *self; flags.hash_stable(hcx, hasher); + inline.hash_stable(hcx, hasher); } } @@ -1160,6 +1163,14 @@ impl<'hir> HashStable<StableHashingContext<'hir>> for hir::TransFnAttrFlags } } +impl<'hir> HashStable<StableHashingContext<'hir>> for attr::InlineAttr { + fn hash_stable<W: StableHasherResult>(&self, + hcx: &mut StableHashingContext<'hir>, + hasher: &mut StableHasher<W>) { + mem::discriminant(self).hash_stable(hcx, hasher); + } +} + impl_stable_hash_for!(struct hir::Freevar { def, span diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index 5658b5b6832..dd581278607 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -15,6 +15,7 @@ // makes all other generics or inline functions that it references // reachable as well. +use hir::TransFnAttrs; use hir::map as hir_map; use hir::def::Def; use hir::def_id::{DefId, CrateNum}; @@ -43,8 +44,8 @@ fn generics_require_inlining(generics: &hir::Generics) -> bool { // Returns true if the given item must be inlined because it may be // monomorphized or it was marked with `#[inline]`. This will only return // true for functions. -fn item_might_be_inlined(item: &hir::Item) -> bool { - if attr::requests_inline(&item.attrs) { +fn item_might_be_inlined(item: &hir::Item, attrs: TransFnAttrs) -> bool { + if attrs.requests_inline() { return true } @@ -60,14 +61,15 @@ fn item_might_be_inlined(item: &hir::Item) -> bool { fn method_might_be_inlined<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_item: &hir::ImplItem, impl_src: DefId) -> bool { - if attr::requests_inline(&impl_item.attrs) || + let trans_fn_attrs = tcx.trans_fn_attrs(impl_item.hir_id.owner_def_id()); + if trans_fn_attrs.requests_inline() || generics_require_inlining(&impl_item.generics) { return true } if let Some(impl_node_id) = tcx.hir.as_local_node_id(impl_src) { match tcx.hir.find(impl_node_id) { Some(hir_map::NodeItem(item)) => - item_might_be_inlined(&item), + item_might_be_inlined(&item, trans_fn_attrs), Some(..) | None => span_bug!(impl_item.span, "impl did is not an item") } @@ -160,7 +162,8 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { match self.tcx.hir.find(node_id) { Some(hir_map::NodeItem(item)) => { match item.node { - hir::ItemFn(..) => item_might_be_inlined(&item), + hir::ItemFn(..) => + item_might_be_inlined(&item, self.tcx.trans_fn_attrs(def_id)), _ => false, } } @@ -176,8 +179,9 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { match impl_item.node { hir::ImplItemKind::Const(..) => true, hir::ImplItemKind::Method(..) => { + let attrs = self.tcx.trans_fn_attrs(def_id); if generics_require_inlining(&impl_item.generics) || - attr::requests_inline(&impl_item.attrs) { + attrs.requests_inline() { true } else { let impl_did = self.tcx @@ -246,7 +250,8 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { hir_map::NodeItem(item) => { match item.node { hir::ItemFn(.., body) => { - if item_might_be_inlined(&item) { + let def_id = self.tcx.hir.local_def_id(item.id); + if item_might_be_inlined(&item, self.tcx.trans_fn_attrs(def_id)) { self.visit_nested_body(body); } } diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index f4b5ffbb7dc..a5f0abb9bc0 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -96,7 +96,6 @@ impl<'tcx> InstanceDef<'tcx> { &self, tcx: TyCtxt<'a, 'tcx, 'tcx> ) -> bool { - use syntax::attr::requests_inline; if self.is_inline(tcx) { return true } @@ -106,8 +105,8 @@ impl<'tcx> InstanceDef<'tcx> { // available to normal end-users. return true } - requests_inline(&self.attrs(tcx)[..]) || - tcx.is_const_fn(self.def_id()) + let trans_fn_attrs = tcx.trans_fn_attrs(self.def_id()); + trans_fn_attrs.requests_inline() || tcx.is_const_fn(self.def_id()) } } diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index d19ab894591..830121b446f 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -832,7 +832,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { } else if let hir::ImplItemKind::Method(ref sig, body) = ast_item.node { let generics = self.tcx.generics_of(def_id); let types = generics.parent_types as usize + generics.types.len(); - let needs_inline = types > 0 || attr::requests_inline(&ast_item.attrs); + let needs_inline = types > 0 || tcx.trans_fn_attrs(def_id).requests_inline(); let is_const_fn = sig.constness == hir::Constness::Const; let ast = if is_const_fn { Some(body) } else { None }; 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> { hir::ItemConst(..) => self.encode_optimized_mir(def_id), hir::ItemFn(_, _, constness, _, ref generics, _) => { let has_tps = generics.ty_params().next().is_some(); - let needs_inline = has_tps || attr::requests_inline(&item.attrs); + let needs_inline = has_tps || tcx.trans_fn_attrs(def_id).requests_inline(); let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir; if needs_inline || constness == hir::Constness::Const || always_encode_mir { self.encode_optimized_mir(def_id) diff --git a/src/librustc_mir/monomorphize/item.rs b/src/librustc_mir/monomorphize/item.rs index 7c86f5a4b1a..6f6f5e13c63 100644 --- a/src/librustc_mir/monomorphize/item.rs +++ b/src/librustc_mir/monomorphize/item.rs @@ -141,8 +141,7 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug { // creating one copy of this `#[inline]` function which may // conflict with upstream crates as it could be an exported // symbol. - let attrs = instance.def.attrs(tcx); - match attr::find_inline_attr(Some(tcx.sess.diagnostic()), &attrs) { + match tcx.trans_fn_attrs(instance.def_id()).inline { InlineAttr::Always => InstantiationMode::LocalCopy, _ => { InstantiationMode::GloballyShared { may_conflict: true } diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index 08a9757fb32..485f870fcca 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -207,7 +207,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> { } let attrs = tcx.get_attrs(callsite.callee); - let hint = attr::find_inline_attr(None, &attrs[..]); + let hint = tcx.trans_fn_attrs(callsite.callee).inline; let hinted = match hint { // Just treat inline(always) as a hint for now, diff --git a/src/librustc_trans/attributes.rs b/src/librustc_trans/attributes.rs index 92447d516c3..89ce6bdbb55 100644 --- a/src/librustc_trans/attributes.rs +++ b/src/librustc_trans/attributes.rs @@ -103,15 +103,13 @@ pub fn set_probestack(cx: &CodegenCx, llfn: ValueRef) { /// Composite function which sets LLVM attributes for function depending on its AST (#[attribute]) /// attributes. pub fn from_fn_attrs(cx: &CodegenCx, llfn: ValueRef, id: DefId) { - use syntax::attr::*; - let attrs = cx.tcx.get_attrs(id); - inline(llfn, find_inline_attr(Some(cx.sess().diagnostic()), &attrs)); + let trans_fn_attrs = cx.tcx.trans_fn_attrs(id); + + inline(llfn, trans_fn_attrs.inline); set_frame_pointer_elimination(cx, llfn); set_probestack(cx, llfn); - let trans_fn_attrs = cx.tcx.trans_fn_attrs(id); - if trans_fn_attrs.flags.contains(TransFnAttrFlags::COLD) { Attribute::Cold.apply_llfn(Function, llfn); } diff --git a/src/librustc_trans_utils/trans_crate.rs b/src/librustc_trans_utils/trans_crate.rs index 7b2cbe140ae..443cece66e2 100644 --- a/src/librustc_trans_utils/trans_crate.rs +++ b/src/librustc_trans_utils/trans_crate.rs @@ -236,9 +236,7 @@ impl TransCrate for MetadataOnlyTransCrate { let _ = tcx.export_name(def_id); let _ = tcx.contains_extern_indicator(def_id); let _ = inst.def.is_inline(tcx); - let attrs = inst.def.attrs(tcx); - let _ = - ::syntax::attr::find_inline_attr(Some(tcx.sess.diagnostic()), &attrs); + let _ = tcx.trans_fn_attrs(def_id); } } _ => {} diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index f85af64bb4b..6793f478dd6 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -41,6 +41,8 @@ use util::nodemap::FxHashMap; use rustc_const_math::ConstInt; use syntax::{abi, ast}; +use syntax::ast::MetaItemKind; +use syntax::attr::{InlineAttr, list_contains_name, mark_used}; use syntax::codemap::Spanned; use syntax::symbol::{Symbol, keywords}; use syntax_pos::{Span, DUMMY_SP}; @@ -1742,6 +1744,39 @@ fn trans_fn_attrs<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefId) -> TransFnAt } else if attr.check_name("naked") { trans_fn_attrs.flags |= TransFnAttrFlags::NAKED; } else if attr.check_name("inline") { + trans_fn_attrs.inline = attrs.iter().fold(InlineAttr::None, |ia, attr| { + if attr.path != "inline" { + return ia; + } + let meta = match attr.meta() { + Some(meta) => meta.node, + None => return ia, + }; + match meta { + MetaItemKind::Word => { + mark_used(attr); + InlineAttr::Hint + } + MetaItemKind::List(ref items) => { + mark_used(attr); + if items.len() != 1 { + span_err!(tcx.sess.diagnostic(), attr.span, E0534, + "expected one argument"); + InlineAttr::None + } else if list_contains_name(&items[..], "always") { + InlineAttr::Always + } else if list_contains_name(&items[..], "never") { + InlineAttr::Never + } else { + span_err!(tcx.sess.diagnostic(), items[0].span, E0535, + "invalid argument"); + + InlineAttr::None + } + } + _ => ia, + } + }); } } diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 6c195a991c2..a0844dc259e 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -3705,6 +3705,75 @@ match r { ``` "##, +E0534: r##" +The `inline` attribute was malformed. + +Erroneous code example: + +```ignore (compile_fail not working here; see Issue #43707) +#[inline()] // error: expected one argument +pub fn something() {} + +fn main() {} +``` + +The parenthesized `inline` attribute requires the parameter to be specified: + +``` +#[inline(always)] +fn something() {} +``` + +or: + +``` +#[inline(never)] +fn something() {} +``` + +Alternatively, a paren-less version of the attribute may be used to hint the +compiler about inlining opportunity: + +``` +#[inline] +fn something() {} +``` + +For more information about the inline attribute, read: +https://doc.rust-lang.org/reference.html#inline-attributes +"##, + +E0535: r##" +An unknown argument was given to the `inline` attribute. + +Erroneous code example: + +```ignore (compile_fail not working here; see Issue #43707) +#[inline(unknown)] // error: invalid argument +pub fn something() {} + +fn main() {} +``` + +The `inline` attribute only supports two arguments: + + * always + * never + +All other arguments given to the `inline` attribute will return this error. +Example: + +``` +#[inline(never)] // ok! +pub fn something() {} + +fn main() {} +``` + +For more information about the inline attribute, https: +read://doc.rust-lang.org/reference.html#inline-attributes +"##, + E0559: r##" An unknown field was specified into an enum's structure variant. diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index d0822b69aa6..4818248129e 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -520,7 +520,7 @@ pub fn find_crate_name(attrs: &[Attribute]) -> Option<Symbol> { first_attr_value_str_by_name(attrs, "crate_name") } -#[derive(Copy, Clone, PartialEq)] +#[derive(Copy, Clone, Hash, PartialEq, RustcEncodable, RustcDecodable)] pub enum InlineAttr { None, Hint, @@ -528,43 +528,6 @@ pub enum InlineAttr { Never, } -/// Determine what `#[inline]` attribute is present in `attrs`, if any. -pub fn find_inline_attr(diagnostic: Option<&Handler>, attrs: &[Attribute]) -> InlineAttr { - attrs.iter().fold(InlineAttr::None, |ia, attr| { - if attr.path != "inline" { - return ia; - } - let meta = match attr.meta() { - Some(meta) => meta.node, - None => return ia, - }; - match meta { - MetaItemKind::Word => { - mark_used(attr); - InlineAttr::Hint - } - MetaItemKind::List(ref items) => { - mark_used(attr); - if items.len() != 1 { - diagnostic.map(|d|{ span_err!(d, attr.span, E0534, "expected one argument"); }); - InlineAttr::None - } else if list_contains_name(&items[..], "always") { - InlineAttr::Always - } else if list_contains_name(&items[..], "never") { - InlineAttr::Never - } else { - diagnostic.map(|d| { - span_err!(d, items[0].span, E0535, "invalid argument"); - }); - - InlineAttr::None - } - } - _ => ia, - } - }) -} - #[derive(Copy, Clone, PartialEq)] pub enum UnwindAttr { Allowed, @@ -610,13 +573,6 @@ pub fn find_unwind_attr(diagnostic: Option<&Handler>, attrs: &[Attribute]) -> Op }) } -/// True if `#[inline]` or `#[inline(always)]` is present in `attrs`. -pub fn requests_inline(attrs: &[Attribute]) -> bool { - match find_inline_attr(None, attrs) { - InlineAttr::Hint | InlineAttr::Always => true, - InlineAttr::None | InlineAttr::Never => false, - } -} /// Tests if a cfg-pattern matches the cfg set pub fn cfg_matches(cfg: &ast::MetaItem, sess: &ParseSess, features: Option<&Features>) -> bool { diff --git a/src/libsyntax/diagnostic_list.rs b/src/libsyntax/diagnostic_list.rs index 84ab0336f16..549ef88afcc 100644 --- a/src/libsyntax/diagnostic_list.rs +++ b/src/libsyntax/diagnostic_list.rs @@ -37,75 +37,6 @@ More details can be found in [RFC 438]. [RFC 438]: https://github.com/rust-lang/rfcs/pull/438 "##, -E0534: r##" -The `inline` attribute was malformed. - -Erroneous code example: - -```ignore (compile_fail not working here; see Issue #43707) -#[inline()] // error: expected one argument -pub fn something() {} - -fn main() {} -``` - -The parenthesized `inline` attribute requires the parameter to be specified: - -``` -#[inline(always)] -fn something() {} -``` - -or: - -``` -#[inline(never)] -fn something() {} -``` - -Alternatively, a paren-less version of the attribute may be used to hint the -compiler about inlining opportunity: - -``` -#[inline] -fn something() {} -``` - -For more information about the inline attribute, read: -https://doc.rust-lang.org/reference.html#inline-attributes -"##, - -E0535: r##" -An unknown argument was given to the `inline` attribute. - -Erroneous code example: - -```ignore (compile_fail not working here; see Issue #43707) -#[inline(unknown)] // error: invalid argument -pub fn something() {} - -fn main() {} -``` - -The `inline` attribute only supports two arguments: - - * always - * never - -All other arguments given to the `inline` attribute will return this error. -Example: - -``` -#[inline(never)] // ok! -pub fn something() {} - -fn main() {} -``` - -For more information about the inline attribute, https: -read://doc.rust-lang.org/reference.html#inline-attributes -"##, - E0536: r##" The `not` cfg-predicate was malformed. |
