@@ -637,6 +637,7 @@ pub fn provide(providers: &mut Providers) {
637637 * providers = Providers {
638638 typeck_item_bodies,
639639 typeck_tables_of,
640+ has_typeck_tables,
640641 closure_type,
641642 closure_kind,
642643 adt_destructor,
@@ -664,55 +665,49 @@ fn adt_destructor<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
664665 tcx. calculate_dtor ( def_id, & mut dropck:: check_drop_impl)
665666}
666667
667- fn typeck_tables_of < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
668- def_id : DefId )
669- -> & ' tcx ty:: TypeckTables < ' tcx > {
670- // Closures' tables come from their outermost function,
671- // as they are part of the same "inference environment".
672- let outer_def_id = tcx. closure_base_def_id ( def_id) ;
673- if outer_def_id != def_id {
674- return tcx. typeck_tables_of ( outer_def_id) ;
675- }
676-
677- let id = tcx. hir . as_local_node_id ( def_id) . unwrap ( ) ;
678- let span = tcx. hir . span ( id) ;
679- let unsupported = || {
680- span_bug ! ( span, "can't type-check body of {:?}" , def_id) ;
681- } ;
682-
683- // Figure out what primary body this item has.
684- let mut fn_decl = None ;
685- let body_id = match tcx. hir . get ( id) {
668+ /// If this def-id is a "primary tables entry", returns `Some((body_id, decl))`
669+ /// with information about it's body-id and fn-decl (if any). Otherwise,
670+ /// returns `None`.
671+ ///
672+ /// If this function returns "some", then `typeck_tables(def_id)` will
673+ /// succeed; if it returns `None`, then `typeck_tables(def_id)` may or
674+ /// may not succeed. In some cases where this function returns `None`
675+ /// (notably closures), `typeck_tables(def_id)` would wind up
676+ /// redirecting to the owning function.
677+ fn primary_body_of < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
678+ id : ast:: NodeId )
679+ -> Option < ( hir:: BodyId , Option < & ' tcx hir:: FnDecl > ) >
680+ {
681+ match tcx. hir . get ( id) {
686682 hir:: map:: NodeItem ( item) => {
687683 match item. node {
688684 hir:: ItemConst ( _, body) |
689- hir:: ItemStatic ( _, _, body) => body ,
690- hir :: ItemFn ( ref decl , .. , body) => {
691- fn_decl = Some ( decl ) ;
692- body
693- }
694- _ => unsupported ( )
685+ hir:: ItemStatic ( _, _, body) =>
686+ Some ( ( body, None ) ) ,
687+ hir :: ItemFn ( ref decl , .. , body ) =>
688+ Some ( ( body, Some ( decl ) ) ) ,
689+ _ =>
690+ None ,
695691 }
696692 }
697693 hir:: map:: NodeTraitItem ( item) => {
698694 match item. node {
699- hir:: TraitItemKind :: Const ( _, Some ( body) ) => body,
700- hir:: TraitItemKind :: Method ( ref sig,
701- hir:: TraitMethod :: Provided ( body) ) => {
702- fn_decl = Some ( & sig. decl ) ;
703- body
704- }
705- _ => unsupported ( )
695+ hir:: TraitItemKind :: Const ( _, Some ( body) ) =>
696+ Some ( ( body, None ) ) ,
697+ hir:: TraitItemKind :: Method ( ref sig, hir:: TraitMethod :: Provided ( body) ) =>
698+ Some ( ( body, Some ( & sig. decl ) ) ) ,
699+ _ =>
700+ None ,
706701 }
707702 }
708703 hir:: map:: NodeImplItem ( item) => {
709704 match item. node {
710- hir:: ImplItemKind :: Const ( _, body) => body ,
711- hir :: ImplItemKind :: Method ( ref sig , body ) => {
712- fn_decl = Some ( & sig . decl ) ;
713- body
714- }
715- _ => unsupported ( )
705+ hir:: ImplItemKind :: Const ( _, body) =>
706+ Some ( ( body , None ) ) ,
707+ hir :: ImplItemKind :: Method ( ref sig , body ) =>
708+ Some ( ( body, Some ( & sig . decl ) ) ) ,
709+ _ =>
710+ None ,
716711 }
717712 }
718713 hir:: map:: NodeExpr ( expr) => {
@@ -723,15 +718,47 @@ fn typeck_tables_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
723718 // Assume that everything other than closures
724719 // is a constant "initializer" expression.
725720 match expr. node {
726- hir:: ExprClosure ( ..) => {
727- // We should've bailed out above for closures.
728- span_bug ! ( expr. span, "unexpected closure" )
729- }
730- _ => hir:: BodyId { node_id : expr. id }
721+ hir:: ExprClosure ( ..) =>
722+ None ,
723+ _ =>
724+ Some ( ( hir:: BodyId { node_id : expr. id } , None ) ) ,
731725 }
732726 }
733- _ => unsupported ( )
734- } ;
727+ _ => None ,
728+ }
729+ }
730+
731+ fn has_typeck_tables < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
732+ def_id : DefId )
733+ -> bool {
734+ // Closures' tables come from their outermost function,
735+ // as they are part of the same "inference environment".
736+ let outer_def_id = tcx. closure_base_def_id ( def_id) ;
737+ if outer_def_id != def_id {
738+ return tcx. has_typeck_tables ( outer_def_id) ;
739+ }
740+
741+ let id = tcx. hir . as_local_node_id ( def_id) . unwrap ( ) ;
742+ primary_body_of ( tcx, id) . is_some ( )
743+ }
744+
745+ fn typeck_tables_of < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
746+ def_id : DefId )
747+ -> & ' tcx ty:: TypeckTables < ' tcx > {
748+ // Closures' tables come from their outermost function,
749+ // as they are part of the same "inference environment".
750+ let outer_def_id = tcx. closure_base_def_id ( def_id) ;
751+ if outer_def_id != def_id {
752+ return tcx. typeck_tables_of ( outer_def_id) ;
753+ }
754+
755+ let id = tcx. hir . as_local_node_id ( def_id) . unwrap ( ) ;
756+ let span = tcx. hir . span ( id) ;
757+
758+ // Figure out what primary body this item has.
759+ let ( body_id, fn_decl) = primary_body_of ( tcx, id) . unwrap_or_else ( || {
760+ span_bug ! ( span, "can't type-check body of {:?}" , def_id) ;
761+ } ) ;
735762 let body = tcx. hir . body ( body_id) ;
736763
737764 Inherited :: build ( tcx, id) . enter ( |inh| {
0 commit comments