about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorFlorian Diebold <flodiebold@gmail.com>2016-11-24 18:25:59 +0100
committerFlorian Diebold <florian.diebold@freiheit.com>2016-11-29 13:04:27 +0100
commitd0ae2c814232bcffd83bbb2e3653dfb8c8746975 (patch)
tree4e4e384d9f0443c737cb23ede27d931aa914006f /src
parentdd1491cfbee8ec271438e6a56123fcc725468f0f (diff)
downloadrust-d0ae2c814232bcffd83bbb2e3653dfb8c8746975.tar.gz
rust-d0ae2c814232bcffd83bbb2e3653dfb8c8746975.zip
Refactor inlined items some more
They don't implement FnLikeNode anymore, instead are handled differently
further up in the call tree. Also, keep less information (just def ids
for the args).
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
         }
     }