@@ -5,6 +5,7 @@ use std::fmt::Debug;
55use std:: hash:: Hash ;
66
77use rustc_ast:: tokenstream:: TokenStream ;
8+ use rustc_data_structures:: sso:: SsoHashSet ;
89use rustc_data_structures:: stable_hasher:: StableHash ;
910use rustc_hir:: def_id:: { CrateNum , DefId , LOCAL_CRATE , LocalDefId , LocalModDefId } ;
1011use rustc_hir:: hir_id:: OwnerId ;
@@ -256,8 +257,8 @@ impl<'tcx> QueryKey for GenericArg<'tcx> {
256257}
257258
258259impl < ' tcx > QueryKey for Ty < ' tcx > {
259- fn default_span ( & self , _ : TyCtxt < ' _ > ) -> Span {
260- DUMMY_SP
260+ fn default_span ( & self , tcx : TyCtxt < ' _ > ) -> Span {
261+ def_id_of_type ( * self ) . map ( |def_id| tcx . def_span ( def_id ) ) . unwrap_or ( DUMMY_SP )
261262 }
262263}
263264
@@ -360,3 +361,58 @@ impl<'tcx> QueryKey for (ty::Instance<'tcx>, CollectionMode) {
360361 self . 0 . default_span ( tcx)
361362 }
362363}
364+
365+ /// Gets a `DefId` associated with a type
366+ ///
367+ /// Visited set is needed to avoid full iteration over
368+ /// deeply nested tuples that have no DefId.
369+ fn def_id_of_type_cached < ' a > ( ty : Ty < ' a > , visited : & mut SsoHashSet < Ty < ' a > > ) -> Option < DefId > {
370+ match * ty. kind ( ) {
371+ ty:: Adt ( adt_def, _) => Some ( adt_def. did ( ) ) ,
372+
373+ ty:: Dynamic ( data, ..) => data. principal_def_id ( ) ,
374+
375+ ty:: Pat ( subty, _) | ty:: Array ( subty, _) | ty:: Slice ( subty) => {
376+ def_id_of_type_cached ( subty, visited)
377+ }
378+
379+ ty:: RawPtr ( ty, _) => def_id_of_type_cached ( ty, visited) ,
380+
381+ ty:: Ref ( _, ty, _) => def_id_of_type_cached ( ty, visited) ,
382+
383+ ty:: Tuple ( tys) => tys. iter ( ) . find_map ( |ty| {
384+ if visited. insert ( ty) {
385+ return def_id_of_type_cached ( ty, visited) ;
386+ }
387+ return None ;
388+ } ) ,
389+
390+ ty:: FnDef ( def_id, _)
391+ | ty:: Closure ( def_id, _)
392+ | ty:: CoroutineClosure ( def_id, _)
393+ | ty:: Coroutine ( def_id, _)
394+ | ty:: CoroutineWitness ( def_id, _)
395+ | ty:: Foreign ( def_id) => Some ( def_id) ,
396+
397+ ty:: Alias ( alias) => Some ( alias. kind . def_id ( ) ) ,
398+
399+ ty:: Bool
400+ | ty:: Char
401+ | ty:: Int ( _)
402+ | ty:: Uint ( _)
403+ | ty:: Str
404+ | ty:: FnPtr ( ..)
405+ | ty:: UnsafeBinder ( _)
406+ | ty:: Placeholder ( ..)
407+ | ty:: Param ( _)
408+ | ty:: Infer ( _)
409+ | ty:: Bound ( ..)
410+ | ty:: Error ( _)
411+ | ty:: Never
412+ | ty:: Float ( _) => None ,
413+ }
414+ }
415+
416+ fn def_id_of_type ( ty : Ty < ' _ > ) -> Option < DefId > {
417+ def_id_of_type_cached ( ty, & mut SsoHashSet :: new ( ) )
418+ }
0 commit comments