@@ -86,6 +86,93 @@ pub use self::on_disk_cache::OnDiskCache;
8686mod profiling_support;
8787pub use self :: profiling_support:: alloc_self_profile_query_strings;
8888
89+ #[ derive( Copy , Clone ) ]
90+ pub struct TyCtxtAt < ' tcx > {
91+ pub tcx : TyCtxt < ' tcx > ,
92+ pub span : Span ,
93+ }
94+
95+ impl Deref for TyCtxtAt < ' tcx > {
96+ type Target = TyCtxt < ' tcx > ;
97+ #[ inline( always) ]
98+ fn deref ( & self ) -> & Self :: Target {
99+ & self . tcx
100+ }
101+ }
102+
103+ #[ derive( Copy , Clone ) ]
104+ pub struct TyCtxtEnsure < ' tcx > {
105+ pub tcx : TyCtxt < ' tcx > ,
106+ }
107+
108+ impl TyCtxt < ' tcx > {
109+ /// Returns a transparent wrapper for `TyCtxt`, which ensures queries
110+ /// are executed instead of just returning their results.
111+ #[ inline( always) ]
112+ pub fn ensure ( self ) -> TyCtxtEnsure < ' tcx > {
113+ TyCtxtEnsure { tcx : self }
114+ }
115+
116+ /// Returns a transparent wrapper for `TyCtxt` which uses
117+ /// `span` as the location of queries performed through it.
118+ #[ inline( always) ]
119+ pub fn at ( self , span : Span ) -> TyCtxtAt < ' tcx > {
120+ TyCtxtAt { tcx : self , span }
121+ }
122+ }
123+
124+ macro_rules! define_callbacks {
125+ ( <$tcx: tt>
126+ $( $( #[ $attr: meta] ) *
127+ [ $( $modifiers: tt) * ] fn $name: ident( $( $K: tt) * ) -> $V: ty, ) * ) => {
128+
129+ impl TyCtxtEnsure <$tcx> {
130+ $( $( #[ $attr] ) *
131+ #[ inline( always) ]
132+ pub fn $name( self , key: query_helper_param_ty!( $( $K) * ) ) {
133+ let key = key. into_query_param( ) ;
134+ let cached = try_get_cached( self . tcx, & self . tcx. query_caches. $name, & key, |_| { } ) ;
135+
136+ let lookup = match cached {
137+ Ok ( ( ) ) => return ,
138+ Err ( lookup) => lookup,
139+ } ;
140+
141+ self . tcx. queries. $name( self . tcx, DUMMY_SP , key, lookup, QueryMode :: Ensure ) ;
142+ } ) *
143+ }
144+
145+ impl TyCtxt <$tcx> {
146+ $( $( #[ $attr] ) *
147+ #[ inline( always) ]
148+ #[ must_use]
149+ pub fn $name( self , key: query_helper_param_ty!( $( $K) * ) ) -> query_stored:: $name<$tcx>
150+ {
151+ self . at( DUMMY_SP ) . $name( key)
152+ } ) *
153+ }
154+
155+ impl TyCtxtAt <$tcx> {
156+ $( $( #[ $attr] ) *
157+ #[ inline( always) ]
158+ pub fn $name( self , key: query_helper_param_ty!( $( $K) * ) ) -> query_stored:: $name<$tcx>
159+ {
160+ let key = key. into_query_param( ) ;
161+ let cached = try_get_cached( self . tcx, & self . tcx. query_caches. $name, & key, |value| {
162+ value. clone( )
163+ } ) ;
164+
165+ let lookup = match cached {
166+ Ok ( value) => return value,
167+ Err ( lookup) => lookup,
168+ } ;
169+
170+ self . tcx. queries. $name( self . tcx, self . span, key, lookup, QueryMode :: Get ) . unwrap( )
171+ } ) *
172+ }
173+ }
174+ }
175+
89176// Each of these queries corresponds to a function pointer field in the
90177// `Providers` struct for requesting a value of that type, and a method
91178// on `tcx: TyCtxt` (and `tcx.at(span)`) for doing that request in a way
@@ -99,6 +186,7 @@ pub use self::profiling_support::alloc_self_profile_query_strings;
99186// as they will raise an fatal error on query cycles instead.
100187
101188rustc_query_append ! { [ define_queries!] [ <' tcx>] }
189+ rustc_query_append ! { [ define_callbacks!] [ <' tcx>] }
102190
103191mod sealed {
104192 use super :: { DefId , LocalDefId } ;
0 commit comments