introduce ability to if we have typeck-tables for a given def-id

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.
This commit is contained in:
Niko Matsakis 2017-04-28 09:52:56 -04:00
parent 2cca2567d9
commit d7d3f197f6
4 changed files with 84 additions and 53 deletions

View File

@ -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) -> (),

View File

@ -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) {

View File

@ -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,
@ -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) => {
@ -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| {

View File

@ -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);