Skip to content

Commit

Permalink
Refactor inlined items some more
Browse files Browse the repository at this point in the history
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).
  • Loading branch information
flodiebold committed Nov 29, 2016
1 parent dd1491c commit d0ae2c8
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 102 deletions.
14 changes: 0 additions & 14 deletions src/librustc/hir/map/blocks.rs
Expand Up @@ -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;
Expand Down Expand Up @@ -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 {
Expand All @@ -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)
Expand All @@ -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
Expand Down
6 changes: 6 additions & 0 deletions src/librustc/hir/mod.rs
Expand Up @@ -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))
Expand Down
69 changes: 24 additions & 45 deletions src/librustc/middle/cstore.rs
Expand Up @@ -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};
Expand Down Expand Up @@ -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")
},
Expand All @@ -196,35 +189,32 @@ 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
}
}

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)
}
}
}

Expand All @@ -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
}
}
}

Expand Down
47 changes: 28 additions & 19 deletions src/librustc_const_eval/eval.rs
Expand Up @@ -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;
Expand Down Expand Up @@ -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
};
Expand All @@ -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
Expand Down Expand Up @@ -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;
}
Expand All @@ -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
}
Expand Down Expand Up @@ -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,
Expand Down
6 changes: 3 additions & 3 deletions src/librustc_metadata/encoder.rs
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand Down

0 comments on commit d0ae2c8

Please sign in to comment.