Skip to content

Commit

Permalink
introduce ability to if we have typeck-tables for a given def-id
Browse files Browse the repository at this point in the history
And use this in save-analysis, which used to read the map directly.
This is an attempt to sidestep the failure occuring on homu that I
cannot reproduce.
  • Loading branch information
nikomatsakis committed Apr 28, 2017
1 parent 2cca256 commit d7d3f19
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 53 deletions.
2 changes: 2 additions & 0 deletions src/librustc/ty/maps.rs
Original file line number Diff line number Diff line change
Expand Up @@ -537,6 +537,8 @@ define_maps! { <'tcx>

[] typeck_tables_of: TypeckTables(DefId) -> &'tcx ty::TypeckTables<'tcx>,

[] has_typeck_tables: TypeckTables(DefId) -> bool,

[] coherent_trait: coherent_trait_dep_node((CrateNum, DefId)) -> (),

[] borrowck: BorrowCheck(DefId) -> (),
Expand Down
14 changes: 9 additions & 5 deletions src/librustc_save_analysis/dump_visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,11 +114,15 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
where F: FnOnce(&mut DumpVisitor<'l, 'tcx, 'll, D>)
{
let item_def_id = self.tcx.hir.local_def_id(item_id);
let tables = self.tcx.typeck_tables_of(item_def_id);
let old_tables = self.save_ctxt.tables;
self.save_ctxt.tables = tables;
f(self);
self.save_ctxt.tables = old_tables;
if self.tcx.has_typeck_tables(item_def_id) {
let tables = self.tcx.typeck_tables_of(item_def_id);
let old_tables = self.save_ctxt.tables;
self.save_ctxt.tables = tables;
f(self);
self.save_ctxt.tables = old_tables;
} else {
f(self)
}
}

pub fn dump_crate_info(&mut self, name: &str, krate: &ast::Crate) {
Expand Down
117 changes: 72 additions & 45 deletions src/librustc_typeck/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -637,6 +637,7 @@ pub fn provide(providers: &mut Providers) {
*providers = Providers {
typeck_item_bodies,
typeck_tables_of,
has_typeck_tables,
closure_type,
closure_kind,
adt_destructor,
Expand Down Expand Up @@ -664,55 +665,49 @@ fn adt_destructor<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
tcx.calculate_dtor(def_id, &mut dropck::check_drop_impl)
}

fn typeck_tables_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
def_id: DefId)
-> &'tcx ty::TypeckTables<'tcx> {
// Closures' tables come from their outermost function,
// as they are part of the same "inference environment".
let outer_def_id = tcx.closure_base_def_id(def_id);
if outer_def_id != def_id {
return tcx.typeck_tables_of(outer_def_id);
}

let id = tcx.hir.as_local_node_id(def_id).unwrap();
let span = tcx.hir.span(id);
let unsupported = || {
span_bug!(span, "can't type-check body of {:?}", def_id);
};

// Figure out what primary body this item has.
let mut fn_decl = None;
let body_id = match tcx.hir.get(id) {
/// If this def-id is a "primary tables entry", returns `Some((body_id, decl))`
/// with information about it's body-id and fn-decl (if any). Otherwise,
/// returns `None`.
///
/// If this function returns "some", then `typeck_tables(def_id)` will
/// succeed; if it returns `None`, then `typeck_tables(def_id)` may or
/// may not succeed. In some cases where this function returns `None`
/// (notably closures), `typeck_tables(def_id)` would wind up
/// redirecting to the owning function.
fn primary_body_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
id: ast::NodeId)
-> Option<(hir::BodyId, Option<&'tcx hir::FnDecl>)>
{
match tcx.hir.get(id) {
hir::map::NodeItem(item) => {
match item.node {
hir::ItemConst(_, body) |
hir::ItemStatic(_, _, body) => body,
hir::ItemFn(ref decl, .., body) => {
fn_decl = Some(decl);
body
}
_ => unsupported()
hir::ItemStatic(_, _, body) =>
Some((body, None)),
hir::ItemFn(ref decl, .., body) =>
Some((body, Some(decl))),
_ =>
None,
}
}
hir::map::NodeTraitItem(item) => {
match item.node {
hir::TraitItemKind::Const(_, Some(body)) => body,
hir::TraitItemKind::Method(ref sig,
hir::TraitMethod::Provided(body)) => {
fn_decl = Some(&sig.decl);
body
}
_ => unsupported()
hir::TraitItemKind::Const(_, Some(body)) =>
Some((body, None)),
hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Provided(body)) =>
Some((body, Some(&sig.decl))),
_ =>
None,
}
}
hir::map::NodeImplItem(item) => {
match item.node {
hir::ImplItemKind::Const(_, body) => body,
hir::ImplItemKind::Method(ref sig, body) => {
fn_decl = Some(&sig.decl);
body
}
_ => unsupported()
hir::ImplItemKind::Const(_, body) =>
Some((body, None)),
hir::ImplItemKind::Method(ref sig, body) =>
Some((body, Some(&sig.decl))),
_ =>
None,
}
}
hir::map::NodeExpr(expr) => {
Expand All @@ -723,15 +718,47 @@ fn typeck_tables_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
// Assume that everything other than closures
// is a constant "initializer" expression.
match expr.node {
hir::ExprClosure(..) => {
// We should've bailed out above for closures.
span_bug!(expr.span, "unexpected closure")
}
_ => hir::BodyId { node_id: expr.id }
hir::ExprClosure(..) =>
None,
_ =>
Some((hir::BodyId { node_id: expr.id }, None)),
}
}
_ => unsupported()
};
_ => None,
}
}

fn has_typeck_tables<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
def_id: DefId)
-> bool {
// Closures' tables come from their outermost function,
// as they are part of the same "inference environment".
let outer_def_id = tcx.closure_base_def_id(def_id);
if outer_def_id != def_id {
return tcx.has_typeck_tables(outer_def_id);
}

let id = tcx.hir.as_local_node_id(def_id).unwrap();
primary_body_of(tcx, id).is_some()
}

fn typeck_tables_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
def_id: DefId)
-> &'tcx ty::TypeckTables<'tcx> {
// Closures' tables come from their outermost function,
// as they are part of the same "inference environment".
let outer_def_id = tcx.closure_base_def_id(def_id);
if outer_def_id != def_id {
return tcx.typeck_tables_of(outer_def_id);
}

let id = tcx.hir.as_local_node_id(def_id).unwrap();
let span = tcx.hir.span(id);

// Figure out what primary body this item has.
let (body_id, fn_decl) = primary_body_of(tcx, id).unwrap_or_else(|| {
span_bug!(span, "can't type-check body of {:?}", def_id);
});
let body = tcx.hir.body(body_id);

Inherited::build(tcx, id).enter(|inh| {
Expand Down
4 changes: 1 addition & 3 deletions src/librustc_typeck/check_unused.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for CheckVisitor<'a, 'tcx> {
pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
let mut used_trait_imports = DefIdSet();
for &body_id in tcx.hir.krate().bodies.keys() {
let item_id = tcx.hir.body_owner(body_id);
let item_def_id = tcx.hir.local_def_id(item_id);

let item_def_id = tcx.hir.body_owner_def_id(body_id);
let tables = tcx.typeck_tables_of(item_def_id);
let imports = &tables.used_trait_imports;
debug!("GatherVisitor: item_def_id={:?} with imports {:#?}", item_def_id, imports);
Expand Down

0 comments on commit d7d3f19

Please sign in to comment.