about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/librustc/hir/map/blocks.rs14
-rw-r--r--src/librustc/hir/mod.rs6
-rw-r--r--src/librustc/middle/cstore.rs69
-rw-r--r--src/librustc_const_eval/eval.rs47
-rw-r--r--src/librustc_metadata/encoder.rs6
-rw-r--r--src/librustc_passes/consts.rs51
6 files changed, 91 insertions, 102 deletions
diff --git a/src/librustc/hir/map/blocks.rs b/src/librustc/hir/map/blocks.rs
index 8116f7fd245..068e7ed8624 100644
--- a/src/librustc/hir/map/blocks.rs
+++ b/src/librustc/hir/map/blocks.rs
@@ -25,7 +25,6 @@ use hir as ast;
 use hir::map::{self, Node};
 use hir::{Expr, FnDecl};
 use hir::intravisit::FnKind;
-use middle::cstore::{InlinedItem, InlinedItemKind};
 use syntax::abi;
 use syntax::ast::{Attribute, Name, NodeId};
 use syntax_pos::Span;
@@ -152,7 +151,6 @@ impl<'a> FnLikeNode<'a> {
             map::NodeTraitItem(tm) => tm.is_fn_like(),
             map::NodeImplItem(_) => true,
             map::NodeExpr(e) => e.is_fn_like(),
-            map::NodeInlinedItem(ii) => ii.is_fn(),
             _ => false
         };
         if fn_like {
@@ -175,21 +173,12 @@ impl<'a> FnLikeNode<'a> {
     }
 
     pub fn body(self) -> ast::ExprId {
-        if let map::NodeInlinedItem(ii) = self.node {
-            return ast::ExprId(ii.body.id);
-        }
         self.handle(|i: ItemFnParts<'a>|  i.body,
                     |_, _, _: &'a ast::MethodSig, _, body: ast::ExprId, _, _|  body,
                     |c: ClosureParts<'a>| c.body)
     }
 
     pub fn decl(self) -> &'a FnDecl {
-        if let map::NodeInlinedItem(&InlinedItem {
-            kind: InlinedItemKind::Fn(ref decl),
-            ..
-        }) = self.node {
-            return &decl;
-        }
         self.handle(|i: ItemFnParts<'a>|  &*i.decl,
                     |_, _, sig: &'a ast::MethodSig, _, _, _, _|  &sig.decl,
                     |c: ClosureParts<'a>| c.decl)
@@ -208,9 +197,6 @@ impl<'a> FnLikeNode<'a> {
     }
 
     pub fn constness(self) -> ast::Constness {
-        if let map::NodeInlinedItem(..) = self.node {
-            return ast::Constness::Const;
-        }
         match self.kind() {
             FnKind::ItemFn(_, _, _, constness, ..) => {
                 constness
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index f66e6788ee7..4fd8f96ba04 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -870,6 +870,12 @@ pub struct Expr {
     pub attrs: ThinVec<Attribute>,
 }
 
+impl Expr {
+    pub fn expr_id(&self) -> ExprId {
+        ExprId(self.id)
+    }
+}
+
 impl fmt::Debug for Expr {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f, "expr({}: {})", self.id, print::expr_to_string(self))
diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs
index 12e7735e4c0..022cca5e7f2 100644
--- a/src/librustc/middle/cstore.rs
+++ b/src/librustc/middle/cstore.rs
@@ -43,7 +43,7 @@ use syntax::symbol::Symbol;
 use syntax_pos::Span;
 use rustc_back::target::Target;
 use hir;
-use hir::intravisit::{self, Visitor};
+use hir::intravisit::Visitor;
 use rustc_back::PanicStrategy;
 
 pub use self::NativeLibraryKind::{NativeStatic, NativeFramework, NativeUnknown};
@@ -140,54 +140,47 @@ pub struct NativeLibrary {
 pub struct InlinedItem {
     pub def_id: DefId,
     pub body: P<hir::Expr>,
-    pub kind: InlinedItemKind,
-}
-
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub enum InlinedItemKind {
-    Const(P<hir::Ty>),
-    Fn(P<hir::FnDecl>)
+    pub const_fn_args: Vec<DefId>,
 }
 
 /// A borrowed version of `hir::InlinedItem`. This is what's encoded when saving
 /// a crate; it then gets read as an InlinedItem.
-#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, Hash, Debug)]
+#[derive(Clone, PartialEq, Eq, RustcEncodable, Hash, Debug)]
 pub struct InlinedItemRef<'a> {
     pub def_id: DefId,
     pub body: &'a hir::Expr,
-    pub kind: InlinedItemKindRef<'a>,
+    pub const_fn_args: Vec<DefId>,
 }
 
-#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, Hash, Debug)]
-pub enum InlinedItemKindRef<'a> {
-    Const(&'a hir::Ty),
-    Fn(&'a hir::FnDecl)
+fn get_fn_args(tcx: TyCtxt, decl: &hir::FnDecl) -> Vec<DefId> {
+    decl.inputs.iter().map(|arg| tcx.expect_def(arg.pat.id).def_id()).collect()
 }
 
 impl<'a> InlinedItemRef<'a> {
-    pub fn from_item<'ast: 'a>(def_id: DefId,
+    pub fn from_item<'b, 'tcx>(def_id: DefId,
                                item: &'a hir::Item,
-                               map: &hir_map::Map<'ast>)
+                               tcx: TyCtxt<'b, 'a, 'tcx>)
                                -> InlinedItemRef<'a> {
-        let (body, kind) = match item.node {
+        let (body, args) = match item.node {
             hir::ItemFn(ref decl, _, _, _, _, body_id) =>
-                (map.expr(body_id), InlinedItemKindRef::Fn(&decl)),
-            hir::ItemConst(ref ty, ref body) => (&**body, InlinedItemKindRef::Const(ty)),
+                (tcx.map.expr(body_id), get_fn_args(tcx, decl)),
+            hir::ItemConst(_, ref body) => (&**body, Vec::new()),
             _ => bug!("InlinedItemRef::from_item wrong kind")
         };
         InlinedItemRef {
             def_id: def_id,
             body: body,
-            kind: kind
+            const_fn_args: args
         }
     }
 
     pub fn from_trait_item(def_id: DefId,
                            item: &'a hir::TraitItem,
-                           _map: &hir_map::Map)
+                           _tcx: TyCtxt)
                            -> InlinedItemRef<'a> {
-        let (body, kind) = match item.node {
-            hir::ConstTraitItem(ref ty, Some(ref body)) => (&**body, InlinedItemKindRef::Const(ty)),
+        let (body, args) = match item.node {
+            hir::ConstTraitItem(_, Some(ref body)) =>
+                (&**body, Vec::new()),
             hir::ConstTraitItem(_, None) => {
                 bug!("InlinedItemRef::from_trait_item called for const without body")
             },
@@ -196,24 +189,25 @@ impl<'a> InlinedItemRef<'a> {
         InlinedItemRef {
             def_id: def_id,
             body: body,
-            kind: kind
+            const_fn_args: args
         }
     }
 
-    pub fn from_impl_item<'ast: 'a>(def_id: DefId,
+    pub fn from_impl_item<'b, 'tcx>(def_id: DefId,
                                     item: &'a hir::ImplItem,
-                                    map: &hir_map::Map<'ast>)
+                                    tcx: TyCtxt<'b, 'a, 'tcx>)
                                     -> InlinedItemRef<'a> {
-        let (body, kind) = match item.node {
+        let (body, args) = match item.node {
             hir::ImplItemKind::Method(ref sig, body_id) =>
-                (map.expr(body_id), InlinedItemKindRef::Fn(&sig.decl)),
-            hir::ImplItemKind::Const(ref ty, ref body) => (&**body, InlinedItemKindRef::Const(ty)),
+                (tcx.map.expr(body_id), get_fn_args(tcx, &sig.decl)),
+            hir::ImplItemKind::Const(_, ref body) =>
+                (&**body, Vec::new()),
             _ => bug!("InlinedItemRef::from_impl_item wrong kind")
         };
         InlinedItemRef {
             def_id: def_id,
             body: body,
-            kind: kind
+            const_fn_args: args
         }
     }
 
@@ -221,10 +215,6 @@ impl<'a> InlinedItemRef<'a> {
         where V: Visitor<'a>
     {
         visitor.visit_expr(&self.body);
-        match self.kind {
-            InlinedItemKindRef::Const(ty) => visitor.visit_ty(ty),
-            InlinedItemKindRef::Fn(decl) => intravisit::walk_fn_decl(visitor, decl)
-        }
     }
 }
 
@@ -233,17 +223,6 @@ impl InlinedItem {
         where V: Visitor<'ast>
     {
         visitor.visit_expr(&self.body);
-        match self.kind {
-            InlinedItemKind::Const(ref ty) => visitor.visit_ty(ty),
-            InlinedItemKind::Fn(ref decl) => intravisit::walk_fn_decl(visitor, decl)
-        }
-    }
-
-    pub fn is_fn(&self) -> bool {
-        match self.kind {
-            InlinedItemKind::Const(_) => false,
-            InlinedItemKind::Fn(_) => true
-        }
     }
 }
 
diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs
index 754bb53c29e..6e074d8f53b 100644
--- a/src/librustc_const_eval/eval.rs
+++ b/src/librustc_const_eval/eval.rs
@@ -17,7 +17,7 @@ use self::EvalHint::*;
 
 use rustc::hir::map as ast_map;
 use rustc::hir::map::blocks::FnLikeNode;
-use rustc::middle::cstore::{InlinedItem, InlinedItemKind};
+use rustc::middle::cstore::InlinedItem;
 use rustc::traits;
 use rustc::hir::def::{Def, CtorKind};
 use rustc::hir::def_id::DefId;
@@ -142,9 +142,8 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         }
         let mut used_substs = false;
         let expr_ty = match tcx.sess.cstore.maybe_get_item_ast(tcx, def_id) {
-            Some((&InlinedItem { body: ref const_expr,
-                                 kind: InlinedItemKind::Const(ref ty), .. }, _)) => {
-                Some((&**const_expr, tcx.ast_ty_to_prim_ty(ty)))
+            Some((&InlinedItem { body: ref const_expr, .. }, _)) => {
+                Some((&**const_expr, Some(tcx.sess.cstore.item_type(tcx, def_id))))
             }
             _ => None
         };
@@ -166,8 +165,9 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 } else {
                     expr_ty
                 }
-            }
-            _ => expr_ty
+            },
+            Some(Def::Const(..)) => expr_ty,
+            _ => None
         };
         // If we used the substitutions, particularly to choose an impl
         // of a trait-associated const, don't cache that, because the next
@@ -195,23 +195,29 @@ fn inline_const_fn_from_external_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         return None;
     }
 
-    let fn_id = match tcx.sess.cstore.maybe_get_item_ast(tcx, def_id) {
-        Some((&InlinedItem { kind: InlinedItemKind::Fn(_), .. }, node_id)) => Some(node_id),
-        _ => None
-    };
+    let fn_id = tcx.sess.cstore.maybe_get_item_ast(tcx, def_id).map(|t| t.1);
     tcx.extern_const_fns.borrow_mut().insert(def_id,
                                              fn_id.unwrap_or(ast::DUMMY_NODE_ID));
     fn_id
 }
 
+pub enum ConstFnNode<'tcx> {
+    Local(FnLikeNode<'tcx>),
+    Inlined(&'tcx InlinedItem)
+}
+
 pub fn lookup_const_fn_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
-                                       -> Option<FnLikeNode<'tcx>>
+                                       -> Option<ConstFnNode<'tcx>>
 {
     let fn_id = if let Some(node_id) = tcx.map.as_local_node_id(def_id) {
         node_id
     } else {
         if let Some(fn_id) = inline_const_fn_from_external_crate(tcx, def_id) {
-            fn_id
+            if let ast_map::NodeInlinedItem(ii) = tcx.map.get(fn_id) {
+                return Some(ConstFnNode::Inlined(ii));
+            } else {
+                bug!("Got const fn from external crate, but it's not inlined")
+            }
         } else {
             return None;
         }
@@ -223,7 +229,7 @@ pub fn lookup_const_fn_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefI
     };
 
     if fn_like.constness() == hir::Constness::Const {
-        Some(fn_like)
+        Some(ConstFnNode::Local(fn_like))
     } else {
         None
     }
@@ -858,16 +864,19 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
               Struct(_) => signal!(e, UnimplementedConstVal("tuple struct constructors")),
               callee => signal!(e, CallOn(callee)),
           };
-          let (decl, body_id) = if let Some(fn_like) = lookup_const_fn_by_id(tcx, did) {
-              (fn_like.decl(), fn_like.body())
-          } else {
-              signal!(e, NonConstPath)
+          let (arg_defs, body_id) = match lookup_const_fn_by_id(tcx, did) {
+              Some(ConstFnNode::Inlined(ii)) => (ii.const_fn_args.clone(), ii.body.expr_id()),
+              Some(ConstFnNode::Local(fn_like)) =>
+                  (fn_like.decl().inputs.iter()
+                   .map(|arg| tcx.expect_def(arg.pat.id).def_id()).collect(),
+                   fn_like.body()),
+              None => signal!(e, NonConstPath),
           };
           let result = tcx.map.expr(body_id);
-          assert_eq!(decl.inputs.len(), args.len());
+          assert_eq!(arg_defs.len(), args.len());
 
           let mut call_args = DefIdMap();
-          for (arg, arg_expr) in decl.inputs.iter().zip(args.iter()) {
+          for (arg, arg_expr) in arg_defs.iter().zip(args.iter()) {
               let arg_hint = ty_hint.erase_hint();
               let arg_val = eval_const_expr_partial(
                   tcx,
diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs
index 3584e6e68fe..67b0be0dfcd 100644
--- a/src/librustc_metadata/encoder.rs
+++ b/src/librustc_metadata/encoder.rs
@@ -521,7 +521,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
                 // (InlinedItemRef::from_trait_item panics otherwise)
                 let trait_def_id = trait_item.container.id();
                 Some(self.encode_inlined_item(
-                    InlinedItemRef::from_trait_item(trait_def_id, ast_item, &tcx.map)
+                    InlinedItemRef::from_trait_item(trait_def_id, ast_item, tcx)
                 ))
             } else {
                 None
@@ -594,7 +594,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
 
             ast: if ast {
                 Some(self.encode_inlined_item(
-                    InlinedItemRef::from_impl_item(impl_def_id, ast_item, &tcx.map)
+                    InlinedItemRef::from_impl_item(impl_def_id, ast_item, tcx)
                 ))
             } else {
                 None
@@ -826,7 +826,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
                 hir::ItemConst(..) |
                 hir::ItemFn(_, _, hir::Constness::Const, ..) => {
                     Some(self.encode_inlined_item(
-                        InlinedItemRef::from_item(def_id, item, &tcx.map)
+                        InlinedItemRef::from_item(def_id, item, tcx)
                     ))
                 }
                 _ => None,
diff --git a/src/librustc_passes/consts.rs b/src/librustc_passes/consts.rs
index 6b791e6907c..94110ca58f8 100644
--- a/src/librustc_passes/consts.rs
+++ b/src/librustc_passes/consts.rs
@@ -27,7 +27,7 @@
 use rustc::dep_graph::DepNode;
 use rustc::ty::cast::CastKind;
 use rustc_const_eval::{ConstEvalErr, lookup_const_fn_by_id, compare_lit_exprs};
-use rustc_const_eval::{eval_const_expr_partial, lookup_const_by_id};
+use rustc_const_eval::{ConstFnNode, eval_const_expr_partial, lookup_const_by_id};
 use rustc_const_eval::ErrKind::{IndexOpFeatureGated, UnimplementedConstVal, MiscCatchAll, Math};
 use rustc_const_eval::ErrKind::{ErroneousReferencedConstant, MiscBinaryOp, NonConstPath};
 use rustc_const_eval::ErrKind::UnresolvedPath;
@@ -180,30 +180,39 @@ impl<'a, 'gcx> CheckCrateVisitor<'a, 'gcx> {
 
     /// Returns true if the call is to a const fn or method.
     fn handle_const_fn_call(&mut self, _expr: &hir::Expr, def_id: DefId, ret_ty: Ty<'gcx>) -> bool {
-        if let Some(fn_like) = lookup_const_fn_by_id(self.tcx, def_id) {
-            let node_id = fn_like.body().node_id();
-            let qualif = match self.tcx.const_qualif_map.borrow_mut().entry(node_id) {
-                Entry::Occupied(entry) => Some(*entry.get()),
-                _ => None
-            };
+        match lookup_const_fn_by_id(self.tcx, def_id) {
+            Some(ConstFnNode::Local(fn_like)) => {
+                let qualif = self.fn_like(fn_like.kind(),
+                                          fn_like.decl(),
+                                          fn_like.body(),
+                                          fn_like.span(),
+                                          fn_like.id());
+
+                self.add_qualif(qualif);
 
-            let qualif = qualif.unwrap_or_else(|| {
-                self.fn_like(fn_like.kind(),
-                             fn_like.decl(),
-                             fn_like.body(),
-                             fn_like.span(),
-                             fn_like.id())
-            });
+                if ret_ty.type_contents(self.tcx).interior_unsafe() {
+                    self.add_qualif(ConstQualif::MUTABLE_MEM);
+                }
 
-            self.add_qualif(qualif);
+                true
+            },
+            Some(ConstFnNode::Inlined(ii)) => {
+                let node_id = ii.body.id;
 
-            if ret_ty.type_contents(self.tcx).interior_unsafe() {
-                self.add_qualif(ConstQualif::MUTABLE_MEM);
-            }
+                let qualif = match self.tcx.const_qualif_map.borrow_mut().entry(node_id) {
+                    Entry::Occupied(entry) => *entry.get(),
+                    _ => bug!("const qualif entry missing for inlined item")
+                };
+
+                self.add_qualif(qualif);
+
+                if ret_ty.type_contents(self.tcx).interior_unsafe() {
+                    self.add_qualif(ConstQualif::MUTABLE_MEM);
+                }
 
-            true
-        } else {
-            false
+                true
+            },
+            None => false
         }
     }