@@ -441,3 +441,93 @@ pub fn test_rc() {
441441 // note: simialar things are likely possible with Ref, RefMut, RefCell,
442442 // Vec and others.
443443}
444+
445+ // --- closures ---
446+
447+ fn get_closure ( p3 : * const i64 , p4 : * const i64 ) -> impl FnOnce ( ) {
448+ let my_local1: i64 = 1 ;
449+ let my_local2: i64 = 2 ;
450+ let p1: * const i64 = & my_local1;
451+
452+ return move || { // captures `my_local2`, `p1`, `p3`, `p4` by value (due to `move`)
453+ let p2: * const i64 = & my_local2;
454+
455+ unsafe {
456+ let v1 = * p1; // $ MISSING: Alert
457+ let v2 = * p2; // GOOD
458+ let v3 = * p3; // GOOD
459+ let v4 = * p4; // $ MISSING: Alert
460+ println ! ( " v1 = {v1} (!)" ) ; // corrupt in practice
461+ println ! ( " v2 = {v2}" ) ;
462+ println ! ( " v3 = {v3}" ) ;
463+ println ! ( " v4 = {v4} (!)" ) ;
464+ }
465+ } ;
466+ } // (`my_local1` goes out of scope, thus `p1` is dangling)
467+
468+ fn with_closure ( ptr : * const i64 , closure : fn ( * const i64 , * const i64 ) ) {
469+ let my_local5: i64 = 5 ;
470+
471+ closure ( ptr,
472+ & my_local5) ;
473+ }
474+
475+ pub fn test_closures ( ) {
476+ let closure;
477+ let my_local3: i64 = 3 ;
478+ {
479+ let my_local4: i64 = 4 ;
480+ closure = get_closure ( & my_local3,
481+ & my_local4) ;
482+ } // (`my_local4` goes out of scope, so `p4` is dangling)
483+
484+ use_the_stack ( ) ;
485+
486+ closure ( ) ;
487+
488+ with_closure ( & my_local3, |p1, p2| {
489+ unsafe {
490+ let v5 = * p1; // GOOD
491+ let v6 = * p2; // GOOD
492+ println ! ( " v5 = {v5}" ) ;
493+ println ! ( " v6 = {v6}" ) ;
494+ }
495+ } ) ;
496+ }
497+
498+ // --- async ---
499+
500+ fn get_async_closure ( p3 : * const i64 , p4 : * const i64 ) -> impl std:: future:: Future < Output = ( ) > {
501+ let my_local1: i64 = 1 ;
502+ let my_local2: i64 = 2 ;
503+ let p1: * const i64 = & my_local1;
504+
505+ return async move { // captures `my_local2`, `p1`, `p3`, `p4` by value (due to `move`)
506+ let p2: * const i64 = & my_local2;
507+
508+ unsafe {
509+ let v1 = * p1; // $ MISSING: Alert
510+ let v2 = * p2; // GOOD
511+ let v3 = * p3; // GOOD
512+ let v4 = * p4; // $ MISSING: Alert
513+ println ! ( " v1 = {v1} (!)" ) ; // corrupt in practice
514+ println ! ( " v2 = {v2}" ) ;
515+ println ! ( " v3 = {v3}" ) ;
516+ println ! ( " v4 = {v4} (!)" ) ;
517+ }
518+ } ;
519+ } // (`my_local1` goes out of scope, thus `p1` is dangling)
520+
521+ pub fn test_async ( ) {
522+ let async_closure;
523+ let my_local3: i64 = 3 ;
524+ {
525+ let my_local4: i64 = 4 ;
526+ async_closure = get_async_closure ( & my_local3,
527+ & my_local4) ;
528+ } // (`my_local4` goes out of scope, so `p4` is dangling)
529+
530+ use_the_stack ( ) ;
531+
532+ futures:: executor:: block_on ( async_closure) ;
533+ }
0 commit comments