about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorWesley Wiser <wwiser@gmail.com>2018-01-30 22:39:23 -0500
committerWesley Wiser <wwiser@gmail.com>2018-03-06 19:58:02 -0500
commit4f840a683aebb40a4eec0285a49962dfbc8f425b (patch)
tree42a46993b1e9c9ecd2658f41aa4cc29bbf3e012d /src
parente8cd6cc23783a6a020d2c14f1a0f343a6267195d (diff)
downloadrust-4f840a683aebb40a4eec0285a49962dfbc8f425b.tar.gz
rust-4f840a683aebb40a4eec0285a49962dfbc8f425b.zip
Add `inline` to `TransFnAttrs`
Part of #47320
Diffstat (limited to 'src')
-rw-r--r--src/librustc/hir/mod.rs11
-rw-r--r--src/librustc/ich/impls_hir.rs11
-rw-r--r--src/librustc/middle/reachable.rs19
-rw-r--r--src/librustc/ty/instance.rs5
-rw-r--r--src/librustc_metadata/encoder.rs4
-rw-r--r--src/librustc_mir/monomorphize/item.rs3
-rw-r--r--src/librustc_mir/transform/inline.rs2
-rw-r--r--src/librustc_trans/attributes.rs8
-rw-r--r--src/librustc_trans_utils/trans_crate.rs4
-rw-r--r--src/librustc_typeck/collect.rs35
-rw-r--r--src/librustc_typeck/diagnostics.rs69
-rw-r--r--src/libsyntax/attr.rs46
-rw-r--r--src/libsyntax/diagnostic_list.rs69
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.