Skip to content

Commit 16eedd2

Browse files
committed
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.
1 parent 1ac338c commit 16eedd2

File tree

11 files changed

+178
-143
lines changed

11 files changed

+178
-143
lines changed

src/librustc/hir/map/blocks.rs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ use hir as ast;
2525
use hir::map::{self, Node};
2626
use hir::{Expr, FnDecl};
2727
use hir::intravisit::FnKind;
28+
use middle::cstore::{InlinedItem, InlinedItemKind};
2829
use syntax::abi;
2930
use syntax::ast::{Attribute, Name, NodeId};
3031
use syntax_pos::Span;
@@ -151,6 +152,7 @@ impl<'a> FnLikeNode<'a> {
151152
map::NodeTraitItem(tm) => tm.is_fn_like(),
152153
map::NodeImplItem(_) => true,
153154
map::NodeExpr(e) => e.is_fn_like(),
155+
map::NodeInlinedItem(ii) => ii.is_fn(),
154156
_ => false
155157
};
156158
if fn_like {
@@ -173,12 +175,18 @@ impl<'a> FnLikeNode<'a> {
173175
}
174176

175177
pub fn body(self) -> ast::ExprId {
178+
if let map::NodeInlinedItem(ii) = self.node {
179+
return ast::ExprId(ii.body.id);
180+
}
176181
self.handle(|i: ItemFnParts<'a>| i.body,
177182
|_, _, _: &'a ast::MethodSig, _, body: ast::ExprId, _, _| body,
178183
|c: ClosureParts<'a>| c.body)
179184
}
180185

181186
pub fn decl(self) -> &'a FnDecl {
187+
if let map::NodeInlinedItem(&InlinedItem { kind: InlinedItemKind::Fn(ref decl), .. }) = self.node {
188+
return &decl;
189+
}
182190
self.handle(|i: ItemFnParts<'a>| &*i.decl,
183191
|_, _, sig: &'a ast::MethodSig, _, _, _, _| &sig.decl,
184192
|c: ClosureParts<'a>| c.decl)
@@ -196,6 +204,21 @@ impl<'a> FnLikeNode<'a> {
196204
|c: ClosureParts| c.id)
197205
}
198206

207+
pub fn constness(self) -> ast::Constness {
208+
if let map::NodeInlinedItem(..) = self.node {
209+
return ast::Constness::Const;
210+
}
211+
match self.kind() {
212+
FnKind::ItemFn(_, _, _, constness, ..) => {
213+
constness
214+
}
215+
FnKind::Method(_, m, ..) => {
216+
m.constness
217+
}
218+
_ => ast::Constness::NotConst
219+
}
220+
}
221+
199222
pub fn kind(self) -> FnKind<'a> {
200223
let item = |p: ItemFnParts<'a>| -> FnKind<'a> {
201224
FnKind::ItemFn(p.name, p.generics, p.unsafety, p.constness, p.abi, p.vis, p.attrs)
@@ -254,7 +277,7 @@ impl<'a> FnLikeNode<'a> {
254277
bug!("impl method FnLikeNode that is not fn-like")
255278
}
256279
}
257-
}
280+
},
258281
map::NodeExpr(e) => match e.node {
259282
ast::ExprClosure(_, ref decl, block, _fn_decl_span) =>
260283
closure(ClosureParts::new(&decl, block, e.id, e.span, &e.attrs)),

src/librustc/hir/map/mod.rs

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ pub use self::definitions::{Definitions, DefKey, DefPath, DefPathData,
1818
use dep_graph::{DepGraph, DepNode};
1919

2020
use middle::cstore::InlinedItem;
21-
use middle::cstore::InlinedItem as II;
2221
use hir::def_id::{CRATE_DEF_INDEX, DefId, DefIndex};
2322

2423
use syntax::abi::Abi;
@@ -61,6 +60,8 @@ pub enum Node<'ast> {
6160
NodeLifetime(&'ast Lifetime),
6261
NodeTyParam(&'ast TyParam),
6362
NodeVisibility(&'ast Visibility),
63+
64+
NodeInlinedItem(&'ast InlinedItem),
6465
}
6566

6667
/// Represents an entry and its parent NodeID.
@@ -120,6 +121,8 @@ impl<'ast> MapEntry<'ast> {
120121
NodeLifetime(n) => EntryLifetime(p, n),
121122
NodeTyParam(n) => EntryTyParam(p, n),
122123
NodeVisibility(n) => EntryVisibility(p, n),
124+
125+
NodeInlinedItem(n) => RootInlinedParent(n),
123126
}
124127
}
125128

@@ -168,6 +171,7 @@ impl<'ast> MapEntry<'ast> {
168171
EntryLifetime(_, n) => NodeLifetime(n),
169172
EntryTyParam(_, n) => NodeTyParam(n),
170173
EntryVisibility(_, n) => NodeVisibility(n),
174+
RootInlinedParent(n) => NodeInlinedItem(n),
171175
_ => return None
172176
})
173177
}
@@ -328,12 +332,8 @@ impl<'ast> Map<'ast> {
328332
EntryVisibility(p, _) =>
329333
id = p,
330334

331-
RootInlinedParent(parent) => match *parent {
332-
InlinedItem::Item(def_id, _) |
333-
InlinedItem::TraitItem(def_id, _) |
334-
InlinedItem::ImplItem(def_id, _) =>
335-
return DepNode::MetaData(def_id)
336-
},
335+
RootInlinedParent(parent) =>
336+
return DepNode::MetaData(parent.def_id),
337337

338338
RootCrate =>
339339
bug!("node {} has crate ancestor but is inlined", id0),
@@ -556,8 +556,7 @@ impl<'ast> Map<'ast> {
556556
pub fn get_parent_did(&self, id: NodeId) -> DefId {
557557
let parent = self.get_parent(id);
558558
match self.find_entry(parent) {
559-
Some(RootInlinedParent(&II::TraitItem(did, _))) |
560-
Some(RootInlinedParent(&II::ImplItem(did, _))) => did,
559+
Some(RootInlinedParent(ii)) => ii.def_id, // TODO: is this wrong for items?
561560
_ => self.local_def_id(parent)
562561
}
563562
}
@@ -962,6 +961,8 @@ impl<'a> NodePrinter for pprust::State<'a> {
962961
// printing.
963962
NodeLocal(_) => bug!("cannot print isolated Local"),
964963
NodeStructCtor(_) => bug!("cannot print isolated StructCtor"),
964+
965+
NodeInlinedItem(_) => bug!("cannot print inlined item"),
965966
}
966967
}
967968
}
@@ -1075,6 +1076,9 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String {
10751076
Some(NodeVisibility(ref vis)) => {
10761077
format!("visibility {:?}{}", vis, id_str)
10771078
}
1079+
Some(NodeInlinedItem(_)) => {
1080+
format!("inlined item {}", id_str)
1081+
}
10781082
None => {
10791083
format!("unknown node{}", id_str)
10801084
}

src/librustc/middle/cstore.rs

Lines changed: 92 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ use syntax::symbol::Symbol;
4343
use syntax_pos::Span;
4444
use rustc_back::target::Target;
4545
use hir;
46-
use hir::intravisit::Visitor;
46+
use hir::intravisit::{self, Visitor};
4747
use rustc_back::PanicStrategy;
4848

4949
pub use self::NativeLibraryKind::{NativeStatic, NativeFramework, NativeUnknown};
@@ -137,18 +137,100 @@ pub struct NativeLibrary {
137137
/// part of the AST that we parse from a file, but it becomes part of the tree
138138
/// that we trans.
139139
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
140-
pub enum InlinedItem {
141-
Item(DefId /* def-id in source crate */, P<hir::Item>),
142-
TraitItem(DefId /* impl id */, P<hir::TraitItem>),
143-
ImplItem(DefId /* impl id */, P<hir::ImplItem>)
140+
pub struct InlinedItem {
141+
pub def_id: DefId,
142+
pub body: P<hir::Expr>,
143+
pub kind: InlinedItemKind,
144+
}
145+
146+
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
147+
pub enum InlinedItemKind {
148+
Const(P<hir::Ty>),
149+
Fn(P<hir::FnDecl>)
150+
}
151+
152+
/// A borrowed version of `hir::InlinedItem`. This is what's encoded when saving
153+
/// a crate; it then gets read as an InlinedItem.
154+
#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, Hash, Debug)]
155+
pub struct InlinedItemRef<'a> {
156+
pub def_id: DefId,
157+
pub body: &'a hir::Expr,
158+
pub kind: InlinedItemKindRef<'a>,
144159
}
145160

146-
/// A borrowed version of `hir::InlinedItem`.
147161
#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, Hash, Debug)]
148-
pub enum InlinedItemRef<'a> {
149-
Item(DefId, &'a hir::Item),
150-
TraitItem(DefId, &'a hir::TraitItem),
151-
ImplItem(DefId, &'a hir::ImplItem)
162+
pub enum InlinedItemKindRef<'a> {
163+
Const(&'a hir::Ty),
164+
Fn(&'a hir::FnDecl)
165+
}
166+
167+
impl<'a> InlinedItemRef<'a> {
168+
pub fn from_item<'ast: 'a>(def_id: DefId, item: &'a hir::Item, map: &hir_map::Map<'ast>) -> InlinedItemRef<'a> {
169+
let (body, kind) = match item.node {
170+
hir::ItemFn(ref decl, _, _, _, _, body_id) => (map.expr(body_id), InlinedItemKindRef::Fn(&decl)),
171+
hir::ItemConst(ref ty, ref body) => (&**body, InlinedItemKindRef::Const(ty)),
172+
_ => bug!("InlinedItemRef::from_item wrong kind")
173+
};
174+
InlinedItemRef {
175+
def_id: def_id,
176+
body: body,
177+
kind: kind
178+
}
179+
}
180+
181+
pub fn from_trait_item(def_id: DefId, item: &'a hir::TraitItem, _map: &hir_map::Map) -> InlinedItemRef<'a> {
182+
let (body, kind) = match item.node {
183+
hir::ConstTraitItem(ref ty, Some(ref body)) => (&**body, InlinedItemKindRef::Const(ty)),
184+
_ => bug!("InlinedItemRef::from_trait_item wrong kind")
185+
};
186+
InlinedItemRef {
187+
def_id: def_id,
188+
body: body,
189+
kind: kind
190+
}
191+
}
192+
193+
pub fn from_impl_item<'ast: 'a>(def_id: DefId, item: &'a hir::ImplItem, map: &hir_map::Map<'ast>) -> InlinedItemRef<'a> {
194+
let (body, kind) = match item.node {
195+
hir::ImplItemKind::Method(ref sig, body_id) => (map.expr(body_id), InlinedItemKindRef::Fn(&sig.decl)),
196+
hir::ImplItemKind::Const(ref ty, ref body) => (&**body, InlinedItemKindRef::Const(ty)),
197+
_ => bug!("InlinedItemRef::from_impl_item wrong kind")
198+
};
199+
InlinedItemRef {
200+
def_id: def_id,
201+
body: body,
202+
kind: kind
203+
}
204+
}
205+
206+
pub fn visit<V>(&self, visitor: &mut V)
207+
where V: Visitor<'a>
208+
{
209+
visitor.visit_expr(&self.body);
210+
match self.kind {
211+
InlinedItemKindRef::Const(ty) => visitor.visit_ty(ty),
212+
InlinedItemKindRef::Fn(decl) => intravisit::walk_fn_decl(visitor, decl)
213+
}
214+
}
215+
}
216+
217+
impl InlinedItem {
218+
pub fn visit<'ast,V>(&'ast self, visitor: &mut V)
219+
where V: Visitor<'ast>
220+
{
221+
visitor.visit_expr(&self.body);
222+
match self.kind {
223+
InlinedItemKind::Const(ref ty) => visitor.visit_ty(ty),
224+
InlinedItemKind::Fn(ref decl) => intravisit::walk_fn_decl(visitor, decl)
225+
}
226+
}
227+
228+
pub fn is_fn(&self) -> bool {
229+
match self.kind {
230+
InlinedItemKind::Const(_) => false,
231+
InlinedItemKind::Fn(_) => true
232+
}
233+
}
152234
}
153235

154236
pub enum LoadedMacro {
@@ -292,18 +374,6 @@ pub trait CrateStore<'tcx> {
292374
fn metadata_encoding_version(&self) -> &[u8];
293375
}
294376

295-
impl InlinedItem {
296-
pub fn visit<'ast,V>(&'ast self, visitor: &mut V)
297-
where V: Visitor<'ast>
298-
{
299-
match *self {
300-
InlinedItem::Item(_, ref i) => visitor.visit_item(&i),
301-
InlinedItem::TraitItem(_, ref ti) => visitor.visit_trait_item(ti),
302-
InlinedItem::ImplItem(_, ref ii) => visitor.visit_impl_item(ii),
303-
}
304-
}
305-
}
306-
307377
// FIXME: find a better place for this?
308378
pub fn validate_crate_name(sess: Option<&Session>, s: &str, sp: Option<Span>) {
309379
let mut err_count = 0;

src/librustc_borrowck/borrowck/gather_loans/mod.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ use syntax_pos::Span;
3030
use rustc::hir;
3131
use rustc::hir::Expr;
3232
use rustc::hir::intravisit;
33-
use rustc::hir::intravisit::Visitor;
33+
use rustc::hir::intravisit::{Visitor, NestedVisitMode};
3434

3535
use self::restrictions::RestrictionResult;
3636

@@ -520,8 +520,12 @@ struct StaticInitializerCtxt<'a, 'tcx: 'a> {
520520
item_id: ast::NodeId
521521
}
522522

523-
impl<'a, 'tcx, 'v> Visitor<'v> for StaticInitializerCtxt<'a, 'tcx> {
524-
fn visit_expr(&mut self, ex: &Expr) {
523+
impl<'a, 'tcx> Visitor<'tcx> for StaticInitializerCtxt<'a, 'tcx> {
524+
fn nested_visit_map(&mut self) -> Option<(&hir::map::Map<'tcx>, NestedVisitMode)> {
525+
Some((&self.bccx.tcx.map, NestedVisitMode::OnlyBodies))
526+
}
527+
528+
fn visit_expr(&mut self, ex: &'tcx Expr) {
525529
if let hir::ExprAddrOf(mutbl, ref base) = ex.node {
526530
let param_env = ty::ParameterEnvironment::for_item(self.bccx.tcx,
527531
self.item_id);
@@ -542,9 +546,9 @@ impl<'a, 'tcx, 'v> Visitor<'v> for StaticInitializerCtxt<'a, 'tcx> {
542546
}
543547
}
544548

545-
pub fn gather_loans_in_static_initializer(bccx: &mut BorrowckCtxt,
546-
item_id: ast::NodeId,
547-
expr: &hir::Expr) {
549+
pub fn gather_loans_in_static_initializer<'a, 'tcx>(bccx: &mut BorrowckCtxt<'a, 'tcx>,
550+
item_id: ast::NodeId,
551+
expr: &'tcx hir::Expr) {
548552

549553
debug!("gather_loans_in_static_initializer(expr={:?})", expr);
550554

src/librustc_const_eval/eval.rs

Lines changed: 9 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use self::EvalHint::*;
1717

1818
use rustc::hir::map as ast_map;
1919
use rustc::hir::map::blocks::FnLikeNode;
20-
use rustc::middle::cstore::InlinedItem;
20+
use rustc::middle::cstore::{InlinedItem, InlinedItemKind};
2121
use rustc::traits;
2222
use rustc::hir::def::{Def, CtorKind};
2323
use rustc::hir::def_id::DefId;
@@ -141,33 +141,9 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
141141
}
142142
let mut used_substs = false;
143143
let expr_ty = match tcx.sess.cstore.maybe_get_item_ast(tcx, def_id) {
144-
Some((&InlinedItem::Item(_, ref item), _)) => match item.node {
145-
hir::ItemConst(ref ty, ref const_expr) => {
146-
Some((&**const_expr, tcx.ast_ty_to_prim_ty(ty)))
147-
},
148-
_ => None
149-
},
150-
Some((&InlinedItem::TraitItem(trait_id, ref ti), _)) => match ti.node {
151-
hir::ConstTraitItem(..) => {
152-
used_substs = true;
153-
if let Some(substs) = substs {
154-
// As mentioned in the comments above for in-crate
155-
// constants, we only try to find the expression for
156-
// a trait-associated const if the caller gives us
157-
// the substitutions for the reference to it.
158-
resolve_trait_associated_const(tcx, ti, trait_id, substs)
159-
} else {
160-
None
161-
}
162-
}
163-
_ => None
164-
},
165-
Some((&InlinedItem::ImplItem(_, ref ii), _)) => match ii.node {
166-
hir::ImplItemKind::Const(ref ty, ref expr) => {
167-
Some((&**expr, tcx.ast_ty_to_prim_ty(ty)))
168-
},
169-
_ => None
170-
},
144+
Some((&InlinedItem { body: ref const_expr, kind: InlinedItemKind::Const(ref ty), .. }, _)) => {
145+
Some((&**const_expr, tcx.ast_ty_to_prim_ty(ty)))
146+
}
171147
_ => None
172148
};
173149
// 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>,
197173
}
198174

199175
let fn_id = match tcx.sess.cstore.maybe_get_item_ast(tcx, def_id) {
200-
Some((&InlinedItem::Item(_, ref item), _)) => Some(item.id),
201-
Some((&InlinedItem::ImplItem(_, ref item), _)) => Some(item.id),
176+
Some((&InlinedItem { kind: InlinedItemKind::Fn(_), .. }, node_id)) => Some(node_id),
202177
_ => None
203178
};
204179
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
224199
None => return None
225200
};
226201

227-
match fn_like.kind() {
228-
FnKind::ItemFn(_, _, _, hir::Constness::Const, ..) => {
229-
Some(fn_like)
230-
}
231-
FnKind::Method(_, m, ..) => {
232-
if m.constness == hir::Constness::Const {
233-
Some(fn_like)
234-
} else {
235-
None
236-
}
237-
}
238-
_ => None
202+
if fn_like.constness() == hir::Constness::Const {
203+
Some(fn_like)
204+
} else {
205+
None
239206
}
240207
}
241208

0 commit comments

Comments
 (0)