@@ -24,14 +24,49 @@ use std::ops::Index;
2424mod internal;
2525pub mod pretty;
2626
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.
2738pub fn stable < ' tcx , S : Stable < ' tcx > > ( item : S ) -> S :: T {
2839 with_tables ( |tables| item. stable ( tables) )
2940}
3041
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.
3153pub fn internal < ' tcx , S : RustcInternal < ' tcx > > ( item : S ) -> S :: T {
3254 with_tables ( |tables| item. internal ( tables) )
3355}
3456
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+
3570impl < ' tcx > Index < stable_mir:: DefId > for Tables < ' tcx > {
3671 type Output = DefId ;
3772
@@ -190,35 +225,83 @@ where
190225 stable_mir:: compiler_interface:: run ( & tables, || init ( & tables, f) )
191226}
192227
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+ /// ```
193274#[ macro_export]
194275macro_rules! run {
195- ( $args: expr, $callback : expr ) => {
196- run!( $args, tcx , $callback )
276+ ( $args: expr, $callback_fn : ident ) => {
277+ run!( $args, $callback_fn ( ) )
197278 } ;
198- ( $args: expr, $tcx : ident , $ callback: expr) => { {
279+ ( $args: expr, $callback: expr) => { {
199280 use rustc_driver:: { Callbacks , Compilation , RunCompiler } ;
200281 use rustc_interface:: { interface, Queries } ;
201282 use stable_mir:: CompilerError ;
202283 use std:: ops:: ControlFlow ;
203284
204- pub struct StableMir <B = ( ) , C = ( ) >
285+ pub struct StableMir <B = ( ) , C = ( ) , F = fn ( ) -> ControlFlow < B , C > >
205286 where
206287 B : Send ,
207288 C : Send ,
289+ F : FnOnce ( ) -> ControlFlow <B , C > + Send ,
208290 {
209291 args: Vec <String >,
210- callback: fn ( TyCtxt < ' _> ) -> ControlFlow < B , C >,
292+ callback: Option < F >,
211293 result: Option <ControlFlow <B , C >>,
212294 }
213295
214- impl <B , C > StableMir <B , C >
296+ impl <B , C , F > StableMir <B , C , F >
215297 where
216298 B : Send ,
217299 C : Send ,
300+ F : FnOnce ( ) -> ControlFlow <B , C > + Send ,
218301 {
219302 /// 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 }
222305 }
223306
224307 /// Runs the compiler against given target and tests it with `test_function`
@@ -238,10 +321,11 @@ macro_rules! run {
238321 }
239322 }
240323
241- impl <B , C > Callbacks for StableMir <B , C >
324+ impl <B , C , F > Callbacks for StableMir <B , C , F >
242325 where
243326 B : Send ,
244327 C : Send ,
328+ F : FnOnce ( ) -> ControlFlow <B , C > + Send ,
245329 {
246330 /// Called after analysis. Return value instructs the compiler whether to
247331 /// continue the compilation afterwards (defaults to `Compilation::Continue`)
@@ -251,20 +335,24 @@ macro_rules! run {
251335 queries: & ' tcx Queries <' tcx>,
252336 ) -> Compilation {
253337 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+ }
260348 } else {
261- Compilation :: Stop
349+ Compilation :: Continue
262350 }
263351 } )
264352 }
265353 }
266354
267- StableMir :: new( $args, |$tcx | $callback) . run( )
355+ StableMir :: new( $args, || $callback) . run( )
268356 } } ;
269357}
270358
0 commit comments