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.
This commit is contained in:
parent
1ac338c2a7
commit
16eedd2a78
@ -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)),
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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,
|
||||
}
|
||||
|
||||
/// A borrowed version of `hir::InlinedItem`.
|
||||
#[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 enum InlinedItemRef<'a> {
|
||||
Item(DefId, &'a hir::Item),
|
||||
TraitItem(DefId, &'a hir::TraitItem),
|
||||
ImplItem(DefId, &'a hir::ImplItem)
|
||||
pub struct InlinedItemRef<'a> {
|
||||
pub def_id: DefId,
|
||||
pub body: &'a hir::Expr,
|
||||
pub kind: InlinedItemKindRef<'a>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, Hash, Debug)]
|
||||
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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
},
|
||||
|
@ -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!()
|
||||
};
|
||||
|
@ -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)
|
||||
|
@ -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() {
|
||||
|
Loading…
Reference in New Issue
Block a user