diff options
| author | Florian Diebold <flodiebold@gmail.com> | 2016-11-01 18:57:13 +0100 |
|---|---|---|
| committer | Florian Diebold <florian.diebold@freiheit.com> | 2016-11-29 13:04:27 +0100 |
| commit | 16eedd2a781ebc5944916bc34d50383c4c3acc1e (patch) | |
| tree | 2581d8bef174a619e0783cb70cfb2362b53defed /src | |
| parent | 1ac338c2a78aa73182916e9425398359ccaf103a (diff) | |
| download | rust-16eedd2a781ebc5944916bc34d50383c4c3acc1e.tar.gz rust-16eedd2a781ebc5944916bc34d50383c4c3acc1e.zip | |
Save bodies of functions for inlining into other crates
This is quite hacky and I hope to refactor it a bit, but at least it seems to work.
Diffstat (limited to 'src')
| -rw-r--r-- | src/librustc/hir/map/blocks.rs | 25 | ||||
| -rw-r--r-- | src/librustc/hir/map/mod.rs | 22 | ||||
| -rw-r--r-- | src/librustc/middle/cstore.rs | 114 | ||||
| -rw-r--r-- | src/librustc_borrowck/borrowck/gather_loans/mod.rs | 16 | ||||
| -rw-r--r-- | src/librustc_const_eval/eval.rs | 51 | ||||
| -rw-r--r-- | src/librustc_metadata/astencode.rs | 20 | ||||
| -rw-r--r-- | src/librustc_metadata/cstore_impl.rs | 26 | ||||
| -rw-r--r-- | src/librustc_metadata/encoder.rs | 8 | ||||
| -rw-r--r-- | src/librustc_mir/hair/cx/mod.rs | 7 | ||||
| -rw-r--r-- | src/librustc_mir/transform/qualify_consts.rs | 14 | ||||
| -rw-r--r-- | src/librustc_passes/consts.rs | 18 |
11 files changed, 178 insertions, 143 deletions
diff --git a/src/librustc/hir/map/blocks.rs b/src/librustc/hir/map/blocks.rs index 0adeb90e697..e4c5fd27b91 100644 --- a/src/librustc/hir/map/blocks.rs +++ b/src/librustc/hir/map/blocks.rs @@ -25,6 +25,7 @@ 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; @@ -151,6 +152,7 @@ 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 { @@ -173,12 +175,18 @@ 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) @@ -196,6 +204,21 @@ impl<'a> FnLikeNode<'a> { |c: ClosureParts| c.id) } + pub fn constness(self) -> ast::Constness { + if let map::NodeInlinedItem(..) = self.node { + return ast::Constness::Const; + } + match self.kind() { + FnKind::ItemFn(_, _, _, constness, ..) => { + constness + } + FnKind::Method(_, m, ..) => { + m.constness + } + _ => ast::Constness::NotConst + } + } + pub fn kind(self) -> FnKind<'a> { let item = |p: ItemFnParts<'a>| -> FnKind<'a> { FnKind::ItemFn(p.name, p.generics, p.unsafety, p.constness, p.abi, p.vis, p.attrs) @@ -254,7 +277,7 @@ impl<'a> FnLikeNode<'a> { bug!("impl method FnLikeNode that is not fn-like") } } - } + }, map::NodeExpr(e) => match e.node { ast::ExprClosure(_, ref decl, block, _fn_decl_span) => closure(ClosureParts::new(&decl, block, e.id, e.span, &e.attrs)), diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 7ef98fcce7e..33cdb428220 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -18,7 +18,6 @@ pub use self::definitions::{Definitions, DefKey, DefPath, DefPathData, use dep_graph::{DepGraph, DepNode}; use middle::cstore::InlinedItem; -use middle::cstore::InlinedItem as II; use hir::def_id::{CRATE_DEF_INDEX, DefId, DefIndex}; use syntax::abi::Abi; @@ -61,6 +60,8 @@ pub enum Node<'ast> { NodeLifetime(&'ast Lifetime), NodeTyParam(&'ast TyParam), NodeVisibility(&'ast Visibility), + + NodeInlinedItem(&'ast InlinedItem), } /// Represents an entry and its parent NodeID. @@ -120,6 +121,8 @@ impl<'ast> MapEntry<'ast> { NodeLifetime(n) => EntryLifetime(p, n), NodeTyParam(n) => EntryTyParam(p, n), NodeVisibility(n) => EntryVisibility(p, n), + + NodeInlinedItem(n) => RootInlinedParent(n), } } @@ -168,6 +171,7 @@ impl<'ast> MapEntry<'ast> { EntryLifetime(_, n) => NodeLifetime(n), EntryTyParam(_, n) => NodeTyParam(n), EntryVisibility(_, n) => NodeVisibility(n), + RootInlinedParent(n) => NodeInlinedItem(n), _ => return None }) } @@ -328,12 +332,8 @@ impl<'ast> Map<'ast> { EntryVisibility(p, _) => id = p, - RootInlinedParent(parent) => match *parent { - InlinedItem::Item(def_id, _) | - InlinedItem::TraitItem(def_id, _) | - InlinedItem::ImplItem(def_id, _) => - return DepNode::MetaData(def_id) - }, + RootInlinedParent(parent) => + return DepNode::MetaData(parent.def_id), RootCrate => bug!("node {} has crate ancestor but is inlined", id0), @@ -556,8 +556,7 @@ impl<'ast> Map<'ast> { pub fn get_parent_did(&self, id: NodeId) -> DefId { let parent = self.get_parent(id); match self.find_entry(parent) { - Some(RootInlinedParent(&II::TraitItem(did, _))) | - Some(RootInlinedParent(&II::ImplItem(did, _))) => did, + Some(RootInlinedParent(ii)) => ii.def_id, // TODO: is this wrong for items? _ => self.local_def_id(parent) } } @@ -962,6 +961,8 @@ impl<'a> NodePrinter for pprust::State<'a> { // printing. NodeLocal(_) => bug!("cannot print isolated Local"), NodeStructCtor(_) => bug!("cannot print isolated StructCtor"), + + NodeInlinedItem(_) => bug!("cannot print inlined item"), } } } @@ -1075,6 +1076,9 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String { Some(NodeVisibility(ref vis)) => { format!("visibility {:?}{}", vis, id_str) } + Some(NodeInlinedItem(_)) => { + format!("inlined item {}", id_str) + } None => { format!("unknown node{}", id_str) } diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 0867e75b9ca..17085e31bfe 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::Visitor; +use hir::intravisit::{self, Visitor}; use rustc_back::PanicStrategy; pub use self::NativeLibraryKind::{NativeStatic, NativeFramework, NativeUnknown}; @@ -137,18 +137,100 @@ pub struct NativeLibrary { /// part of the AST that we parse from a file, but it becomes part of the tree /// that we trans. #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub enum InlinedItem { - Item(DefId /* def-id in source crate */, P<hir::Item>), - TraitItem(DefId /* impl id */, P<hir::TraitItem>), - ImplItem(DefId /* impl id */, P<hir::ImplItem>) +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>) +} + +/// 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)] +pub struct InlinedItemRef<'a> { + pub def_id: DefId, + pub body: &'a hir::Expr, + pub kind: InlinedItemKindRef<'a>, } -/// A borrowed version of `hir::InlinedItem`. #[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, Hash, Debug)] -pub enum InlinedItemRef<'a> { - Item(DefId, &'a hir::Item), - TraitItem(DefId, &'a hir::TraitItem), - ImplItem(DefId, &'a hir::ImplItem) +pub enum InlinedItemKindRef<'a> { + Const(&'a hir::Ty), + Fn(&'a hir::FnDecl) +} + +impl<'a> InlinedItemRef<'a> { + pub fn from_item<'ast: 'a>(def_id: DefId, item: &'a hir::Item, map: &hir_map::Map<'ast>) -> InlinedItemRef<'a> { + let (body, kind) = 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)), + _ => bug!("InlinedItemRef::from_item wrong kind") + }; + InlinedItemRef { + def_id: def_id, + body: body, + kind: kind + } + } + + pub fn from_trait_item(def_id: DefId, item: &'a hir::TraitItem, _map: &hir_map::Map) -> InlinedItemRef<'a> { + let (body, kind) = match item.node { + hir::ConstTraitItem(ref ty, Some(ref body)) => (&**body, InlinedItemKindRef::Const(ty)), + _ => bug!("InlinedItemRef::from_trait_item wrong kind") + }; + InlinedItemRef { + def_id: def_id, + body: body, + kind: kind + } + } + + pub fn from_impl_item<'ast: 'a>(def_id: DefId, item: &'a hir::ImplItem, map: &hir_map::Map<'ast>) -> InlinedItemRef<'a> { + let (body, kind) = 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)), + _ => bug!("InlinedItemRef::from_impl_item wrong kind") + }; + InlinedItemRef { + def_id: def_id, + body: body, + kind: kind + } + } + + pub fn visit<V>(&self, visitor: &mut V) + 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) + } + } +} + +impl InlinedItem { + pub fn visit<'ast,V>(&'ast self, visitor: &mut V) + 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 + } + } } pub enum LoadedMacro { @@ -292,18 +374,6 @@ pub trait CrateStore<'tcx> { fn metadata_encoding_version(&self) -> &[u8]; } -impl InlinedItem { - pub fn visit<'ast,V>(&'ast self, visitor: &mut V) - where V: Visitor<'ast> - { - match *self { - InlinedItem::Item(_, ref i) => visitor.visit_item(&i), - InlinedItem::TraitItem(_, ref ti) => visitor.visit_trait_item(ti), - InlinedItem::ImplItem(_, ref ii) => visitor.visit_impl_item(ii), - } - } -} - // FIXME: find a better place for this? pub fn validate_crate_name(sess: Option<&Session>, s: &str, sp: Option<Span>) { let mut err_count = 0; diff --git a/src/librustc_borrowck/borrowck/gather_loans/mod.rs b/src/librustc_borrowck/borrowck/gather_loans/mod.rs index 8f2afa7f808..96faf97d609 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/mod.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/mod.rs @@ -30,7 +30,7 @@ use syntax_pos::Span; use rustc::hir; use rustc::hir::Expr; use rustc::hir::intravisit; -use rustc::hir::intravisit::Visitor; +use rustc::hir::intravisit::{Visitor, NestedVisitMode}; use self::restrictions::RestrictionResult; @@ -520,8 +520,12 @@ struct StaticInitializerCtxt<'a, 'tcx: 'a> { item_id: ast::NodeId } -impl<'a, 'tcx, 'v> Visitor<'v> for StaticInitializerCtxt<'a, 'tcx> { - fn visit_expr(&mut self, ex: &Expr) { +impl<'a, 'tcx> Visitor<'tcx> for StaticInitializerCtxt<'a, 'tcx> { + fn nested_visit_map(&mut self) -> Option<(&hir::map::Map<'tcx>, NestedVisitMode)> { + Some((&self.bccx.tcx.map, NestedVisitMode::OnlyBodies)) + } + + fn visit_expr(&mut self, ex: &'tcx Expr) { if let hir::ExprAddrOf(mutbl, ref base) = ex.node { let param_env = ty::ParameterEnvironment::for_item(self.bccx.tcx, self.item_id); @@ -542,9 +546,9 @@ impl<'a, 'tcx, 'v> Visitor<'v> for StaticInitializerCtxt<'a, 'tcx> { } } -pub fn gather_loans_in_static_initializer(bccx: &mut BorrowckCtxt, - item_id: ast::NodeId, - expr: &hir::Expr) { +pub fn gather_loans_in_static_initializer<'a, 'tcx>(bccx: &mut BorrowckCtxt<'a, 'tcx>, + item_id: ast::NodeId, + expr: &'tcx hir::Expr) { debug!("gather_loans_in_static_initializer(expr={:?})", expr); diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs index 61986efbf4f..fb5cff56950 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; +use rustc::middle::cstore::{InlinedItem, InlinedItemKind}; use rustc::traits; use rustc::hir::def::{Def, CtorKind}; use rustc::hir::def_id::DefId; @@ -141,33 +141,9 @@ 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::Item(_, ref item), _)) => match item.node { - hir::ItemConst(ref ty, ref const_expr) => { - Some((&**const_expr, tcx.ast_ty_to_prim_ty(ty))) - }, - _ => None - }, - Some((&InlinedItem::TraitItem(trait_id, ref ti), _)) => match ti.node { - hir::ConstTraitItem(..) => { - used_substs = true; - if let Some(substs) = substs { - // As mentioned in the comments above for in-crate - // constants, we only try to find the expression for - // a trait-associated const if the caller gives us - // the substitutions for the reference to it. - resolve_trait_associated_const(tcx, ti, trait_id, substs) - } else { - None - } - } - _ => None - }, - Some((&InlinedItem::ImplItem(_, ref ii), _)) => match ii.node { - hir::ImplItemKind::Const(ref ty, ref expr) => { - Some((&**expr, tcx.ast_ty_to_prim_ty(ty))) - }, - _ => None - }, + Some((&InlinedItem { body: ref const_expr, kind: InlinedItemKind::Const(ref ty), .. }, _)) => { + Some((&**const_expr, tcx.ast_ty_to_prim_ty(ty))) + } _ => None }; // If we used the substitutions, particularly to choose an impl @@ -197,8 +173,7 @@ fn inline_const_fn_from_external_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } let fn_id = match tcx.sess.cstore.maybe_get_item_ast(tcx, def_id) { - Some((&InlinedItem::Item(_, ref item), _)) => Some(item.id), - Some((&InlinedItem::ImplItem(_, ref item), _)) => Some(item.id), + Some((&InlinedItem { kind: InlinedItemKind::Fn(_), .. }, node_id)) => Some(node_id), _ => None }; tcx.extern_const_fns.borrow_mut().insert(def_id, @@ -224,18 +199,10 @@ pub fn lookup_const_fn_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefI None => return None }; - match fn_like.kind() { - FnKind::ItemFn(_, _, _, hir::Constness::Const, ..) => { - Some(fn_like) - } - FnKind::Method(_, m, ..) => { - if m.constness == hir::Constness::Const { - Some(fn_like) - } else { - None - } - } - _ => None + if fn_like.constness() == hir::Constness::Const { + Some(fn_like) + } else { + None } } diff --git a/src/librustc_metadata/astencode.rs b/src/librustc_metadata/astencode.rs index 69e1ecb5f81..8a24062f8f3 100644 --- a/src/librustc_metadata/astencode.rs +++ b/src/librustc_metadata/astencode.rs @@ -46,11 +46,7 @@ enum TableEntry<'tcx> { impl<'a, 'tcx> EncodeContext<'a, 'tcx> { pub fn encode_inlined_item(&mut self, ii: InlinedItemRef<'tcx>) -> Lazy<Ast<'tcx>> { let mut id_visitor = IdRangeComputingVisitor::new(&self.tcx.map); - match ii { - InlinedItemRef::Item(_, i) => id_visitor.visit_item(i), - InlinedItemRef::TraitItem(_, ti) => id_visitor.visit_trait_item(ti), - InlinedItemRef::ImplItem(_, ii) => id_visitor.visit_impl_item(ii), - } + ii.visit(&mut id_visitor); let ii_pos = self.position(); ii.encode(self).unwrap(); @@ -61,11 +57,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { ecx: self, count: 0, }; - match ii { - InlinedItemRef::Item(_, i) => visitor.visit_item(i), - InlinedItemRef::TraitItem(_, ti) => visitor.visit_trait_item(ti), - InlinedItemRef::ImplItem(_, ii) => visitor.visit_impl_item(ii), - } + ii.visit(&mut visitor); visitor.count }; @@ -127,17 +119,13 @@ pub fn decode_inlined_item<'a, 'tcx>(cdata: &CrateMetadata, }]; let ii = ast.item.decode((cdata, tcx, id_ranges)); + let item_node_id = tcx.sess.next_node_id(); let ii = ast_map::map_decoded_item(&tcx.map, parent_def_path, parent_did, ii, - tcx.sess.next_node_id()); + item_node_id); - let item_node_id = match ii { - &InlinedItem::Item(_, ref i) => i.id, - &InlinedItem::TraitItem(_, ref ti) => ti.id, - &InlinedItem::ImplItem(_, ref ii) => ii.id, - }; let inlined_did = tcx.map.local_def_id(item_node_id); let ty = tcx.item_type(orig_did); let generics = tcx.item_generics(orig_did); diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 4b90d925972..573b2f6d2a6 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -443,12 +443,10 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { let find_inlined_item_root = |inlined_item_id| { let mut node = inlined_item_id; - let mut path = Vec::with_capacity(10); // If we can't find the inline root after a thousand hops, we can // be pretty sure there's something wrong with the HIR map. for _ in 0 .. 1000 { - path.push(node); let parent_node = tcx.map.get_parent_node(node); if parent_node == node { return node; @@ -464,27 +462,9 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { .borrow_mut() .insert(def_id, None); } - Some(&InlinedItem::Item(d, ref item)) => { - assert_eq!(d, def_id); - let inlined_root_node_id = find_inlined_item_root(item.id); - cache_inlined_item(def_id, item.id, inlined_root_node_id); - } - Some(&InlinedItem::TraitItem(_, ref trait_item)) => { - let inlined_root_node_id = find_inlined_item_root(trait_item.id); - cache_inlined_item(def_id, trait_item.id, inlined_root_node_id); - - // Associated consts already have to be evaluated in `typeck`, so - // the logic to do that already exists in `middle`. In order to - // reuse that code, it needs to be able to look up the traits for - // inlined items. - let ty_trait_item = tcx.associated_item(def_id).clone(); - let trait_item_def_id = tcx.map.local_def_id(trait_item.id); - tcx.associated_items.borrow_mut() - .insert(trait_item_def_id, ty_trait_item); - } - Some(&InlinedItem::ImplItem(_, ref impl_item)) => { - let inlined_root_node_id = find_inlined_item_root(impl_item.id); - cache_inlined_item(def_id, impl_item.id, inlined_root_node_id); + Some(&InlinedItem { ref body, .. }) => { + let inlined_root_node_id = find_inlined_item_root(body.id); + cache_inlined_item(def_id, inlined_root_node_id, inlined_root_node_id); } } diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index ca730afc52a..afb88cf3ddf 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -518,7 +518,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { ast: if trait_item.kind == ty::AssociatedKind::Const { let trait_def_id = trait_item.container.id(); - Some(self.encode_inlined_item(InlinedItemRef::TraitItem(trait_def_id, ast_item))) + Some(self.encode_inlined_item(InlinedItemRef::from_trait_item(trait_def_id, ast_item, &tcx.map))) } else { None }, @@ -527,6 +527,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } fn encode_info_for_impl_item(&mut self, def_id: DefId) -> Entry<'tcx> { + let tcx = self.tcx; + let node_id = self.tcx.map.as_local_node_id(def_id).unwrap(); let ast_item = self.tcx.map.expect_impl_item(node_id); let impl_item = self.tcx.associated_item(def_id); @@ -587,7 +589,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { predicates: Some(self.encode_predicates(def_id)), ast: if ast { - Some(self.encode_inlined_item(InlinedItemRef::ImplItem(impl_def_id, ast_item))) + Some(self.encode_inlined_item(InlinedItemRef::from_impl_item(impl_def_id, ast_item, &tcx.map))) } else { None }, @@ -817,7 +819,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { ast: match item.node { hir::ItemConst(..) | hir::ItemFn(_, _, hir::Constness::Const, ..) => { - Some(self.encode_inlined_item(InlinedItemRef::Item(def_id, item))) + Some(self.encode_inlined_item(InlinedItemRef::from_item(def_id, item, &tcx.map))) } _ => None, }, diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs index cfeac606f03..32639cc3f86 100644 --- a/src/librustc_mir/hair/cx/mod.rs +++ b/src/librustc_mir/hair/cx/mod.rs @@ -23,7 +23,6 @@ use rustc_const_eval as const_eval; use rustc_data_structures::indexed_vec::Idx; use rustc::dep_graph::DepNode; use rustc::hir::def_id::DefId; -use rustc::hir::intravisit::FnKind; use rustc::hir::map::blocks::FnLikeNode; use rustc::infer::InferCtxt; use rustc::ty::subst::Subst; @@ -51,11 +50,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { MirSource::Static(..) => hir::Constness::Const, MirSource::Fn(id) => { let fn_like = FnLikeNode::from_node(infcx.tcx.map.get(id)); - match fn_like.map(|f| f.kind()) { - Some(FnKind::ItemFn(_, _, _, c, ..)) => c, - Some(FnKind::Method(_, m, ..)) => m.constness, - _ => hir::Constness::NotConst - } + fn_like.map_or(hir::Constness::NotConst, |f| f.constness()) } MirSource::Promoted(..) => bug!() }; diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 4ff2beb3fdb..57929879f94 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -19,7 +19,6 @@ use rustc_data_structures::indexed_vec::{IndexVec, Idx}; use rustc::hir; use rustc::hir::map as hir_map; use rustc::hir::def_id::DefId; -use rustc::hir::intravisit::FnKind; use rustc::hir::map::blocks::FnLikeNode; use rustc::traits::{self, Reveal}; use rustc::ty::{self, TyCtxt, Ty}; @@ -116,15 +115,10 @@ impl fmt::Display for Mode { pub fn is_const_fn(tcx: TyCtxt, def_id: DefId) -> bool { if let Some(node_id) = tcx.map.as_local_node_id(def_id) { - let fn_like = FnLikeNode::from_node(tcx.map.get(node_id)); - match fn_like.map(|f| f.kind()) { - Some(FnKind::ItemFn(_, _, _, c, ..)) => { - c == hir::Constness::Const - } - Some(FnKind::Method(_, m, ..)) => { - m.constness == hir::Constness::Const - } - _ => false + if let Some(fn_like) = FnLikeNode::from_node(tcx.map.get(node_id)) { + fn_like.constness() == hir::Constness::Const + } else { + false } } else { tcx.sess.cstore.is_const_fn(def_id) diff --git a/src/librustc_passes/consts.rs b/src/librustc_passes/consts.rs index 626af7db325..729cc773568 100644 --- a/src/librustc_passes/consts.rs +++ b/src/librustc_passes/consts.rs @@ -181,11 +181,19 @@ 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 qualif = self.fn_like(fn_like.kind(), - fn_like.decl(), - fn_like.body(), - fn_like.span(), - fn_like.id()); + let qualif = match self.tcx.const_qualif_map.borrow_mut().entry(fn_like.body().node_id()) { + Entry::Occupied(entry) => Some(*entry.get()), + _ => None + }; + + let qualif = qualif.unwrap_or_else(|| { + self.fn_like(fn_like.kind(), + fn_like.decl(), + fn_like.body(), + fn_like.span(), + fn_like.id()) + }); + self.add_qualif(qualif); if ret_ty.type_contents(self.tcx).interior_unsafe() { |
