@@ -24,14 +24,49 @@ use std::ops::Index;
24
24
mod internal;
25
25
pub mod pretty;
26
26
27
+ /// Convert an internal Rust compiler item into its stable counterpart, if one exists.
28
+ ///
29
+ /// # Warning
30
+ ///
31
+ /// This function is unstable, and it's behavior may change at any point.
32
+ /// E.g.: Items that were previously supported, may no longer be supported, or its translation may
33
+ /// change.
34
+ ///
35
+ /// # Panics
36
+ ///
37
+ /// This function will panic if StableMIR has not been properly initialized.
27
38
pub fn stable < ' tcx , S : Stable < ' tcx > > ( item : S ) -> S :: T {
28
39
with_tables ( |tables| item. stable ( tables) )
29
40
}
30
41
42
+ /// Convert a stable item into its internal Rust compiler counterpart, if one exists.
43
+ ///
44
+ /// # Warning
45
+ ///
46
+ /// This function is unstable, and it's behavior may change at any point.
47
+ /// Not every stable item can be converted to an internal one.
48
+ /// Furthermore, items that were previously supported, may no longer be supported in newer versions.
49
+ ///
50
+ /// # Panics
51
+ ///
52
+ /// This function will panic if StableMIR has not been properly initialized.
31
53
pub fn internal < ' tcx , S : RustcInternal < ' tcx > > ( item : S ) -> S :: T {
32
54
with_tables ( |tables| item. internal ( tables) )
33
55
}
34
56
57
+ /// Retrieve the internal Rust compiler type context.
58
+ ///
59
+ /// # Warning
60
+ ///
61
+ /// This function is unstable, and it's behavior may change at any point.
62
+ ///
63
+ /// # Panics
64
+ ///
65
+ /// This function will panic if StableMIR has not been properly initialized.
66
+ pub fn tcx < ' tcx > ( ) -> TyCtxt < ' tcx > {
67
+ with_tables ( |tables| tables. tcx )
68
+ }
69
+
35
70
impl < ' tcx > Index < stable_mir:: DefId > for Tables < ' tcx > {
36
71
type Output = DefId ;
37
72
@@ -190,35 +225,83 @@ where
190
225
stable_mir:: compiler_interface:: run ( & tables, || init ( & tables, f) )
191
226
}
192
227
228
+ /// Instantiate and run the compiler with the provided arguments and callback.
229
+ ///
230
+ /// The callback will be invoked after the compiler ran all its analysis, but before code generation.
231
+ /// Note that this macro accepts two different formats for the callback:
232
+ /// 1. An ident that resolves to a function that accepts no argument and returns `ControlFlow<B, C>`
233
+ /// ```ignore(needs-extern-crate)
234
+ /// # extern crate rustc_driver;
235
+ /// # extern crate rustc_interface;
236
+ /// # #[macro_use]
237
+ /// # extern crate rustc_smir;
238
+ /// # extern crate stable_mir;
239
+ /// #
240
+ /// # fn main() {
241
+ /// # use std::ops::ControlFlow;
242
+ /// # use stable_mir::CompilerError;
243
+ /// fn analyze_code() -> ControlFlow<(), ()> {
244
+ /// // Your code goes in here.
245
+ /// # ControlFlow::Continue(())
246
+ /// }
247
+ /// # let args = vec!["--verbose".to_string()];
248
+ /// let result = run!(args, analyze_code);
249
+ /// # assert_eq!(result, Err(CompilerError::Skipped))
250
+ /// # }
251
+ /// ```
252
+ /// 2. An expression that represents the body of a closure:
253
+ /// ```ignore(needs-extern-crate)
254
+ /// # extern crate rustc_driver;
255
+ /// # extern crate rustc_interface;
256
+ /// # #[macro_use]
257
+ /// # extern crate rustc_smir;
258
+ /// # extern crate stable_mir;
259
+ /// #
260
+ /// # fn main() {
261
+ /// # use std::ops::ControlFlow;
262
+ /// # use stable_mir::CompilerError;
263
+ /// fn analyze_code(extra_args: Vec<String>) -> ControlFlow<(), ()> {
264
+ /// # let _ = extra_args;
265
+ /// // Your code goes in here.
266
+ /// # ControlFlow::Continue(())
267
+ /// }
268
+ /// # let args = vec!["--verbose".to_string()];
269
+ /// # let extra_args = vec![];
270
+ /// let result = run!(args, analyze_code(extra_args));
271
+ /// # assert_eq!(result, Err(CompilerError::Skipped))
272
+ /// # }
273
+ /// ```
193
274
#[ macro_export]
194
275
macro_rules! run {
195
- ( $args: expr, $callback : expr ) => {
196
- run!( $args, tcx , $callback )
276
+ ( $args: expr, $callback_fn : ident ) => {
277
+ run!( $args, $callback_fn ( ) )
197
278
} ;
198
- ( $args: expr, $tcx : ident , $ callback: expr) => { {
279
+ ( $args: expr, $callback: expr) => { {
199
280
use rustc_driver:: { Callbacks , Compilation , RunCompiler } ;
200
281
use rustc_interface:: { interface, Queries } ;
201
282
use stable_mir:: CompilerError ;
202
283
use std:: ops:: ControlFlow ;
203
284
204
- pub struct StableMir <B = ( ) , C = ( ) >
285
+ pub struct StableMir <B = ( ) , C = ( ) , F = fn ( ) -> ControlFlow < B , C > >
205
286
where
206
287
B : Send ,
207
288
C : Send ,
289
+ F : FnOnce ( ) -> ControlFlow <B , C > + Send ,
208
290
{
209
291
args: Vec <String >,
210
- callback: fn ( TyCtxt < ' _> ) -> ControlFlow < B , C >,
292
+ callback: Option < F >,
211
293
result: Option <ControlFlow <B , C >>,
212
294
}
213
295
214
- impl <B , C > StableMir <B , C >
296
+ impl <B , C , F > StableMir <B , C , F >
215
297
where
216
298
B : Send ,
217
299
C : Send ,
300
+ F : FnOnce ( ) -> ControlFlow <B , C > + Send ,
218
301
{
219
302
/// Creates a new `StableMir` instance, with given test_function and arguments.
220
- pub fn new( args: Vec <String >, callback: fn ( TyCtxt < ' _> ) -> ControlFlow < B , C > ) -> Self {
221
- StableMir { args, callback, result: None }
303
+ pub fn new( args: Vec <String >, callback: F ) -> Self {
304
+ StableMir { args, callback: Some ( callback ) , result: None }
222
305
}
223
306
224
307
/// Runs the compiler against given target and tests it with `test_function`
@@ -238,10 +321,11 @@ macro_rules! run {
238
321
}
239
322
}
240
323
241
- impl <B , C > Callbacks for StableMir <B , C >
324
+ impl <B , C , F > Callbacks for StableMir <B , C , F >
242
325
where
243
326
B : Send ,
244
327
C : Send ,
328
+ F : FnOnce ( ) -> ControlFlow <B , C > + Send ,
245
329
{
246
330
/// Called after analysis. Return value instructs the compiler whether to
247
331
/// continue the compilation afterwards (defaults to `Compilation::Continue`)
@@ -251,20 +335,24 @@ macro_rules! run {
251
335
queries: & ' tcx Queries <' tcx>,
252
336
) -> Compilation {
253
337
queries. global_ctxt( ) . unwrap( ) . enter( |tcx| {
254
- rustc_internal:: run( tcx, || {
255
- self . result = Some ( ( self . callback) ( tcx) ) ;
256
- } )
257
- . unwrap( ) ;
258
- if self . result. as_ref( ) . is_some_and( |val| val. is_continue( ) ) {
259
- Compilation :: Continue
338
+ if let Some ( callback) = self . callback. take( ) {
339
+ rustc_internal:: run( tcx, || {
340
+ self . result = Some ( ( callback) ( ) ) ;
341
+ } )
342
+ . unwrap( ) ;
343
+ if self . result. as_ref( ) . is_some_and( |val| val. is_continue( ) ) {
344
+ Compilation :: Continue
345
+ } else {
346
+ Compilation :: Stop
347
+ }
260
348
} else {
261
- Compilation :: Stop
349
+ Compilation :: Continue
262
350
}
263
351
} )
264
352
}
265
353
}
266
354
267
- StableMir :: new( $args, |$tcx | $callback) . run( )
355
+ StableMir :: new( $args, || $callback) . run( )
268
356
} } ;
269
357
}
270
358
0 commit comments