@@ -531,3 +531,52 @@ pub fn test_async() {
531531
532532 futures:: executor:: block_on ( async_closure) ;
533533}
534+
535+ // --- lifetime annotations ---
536+
537+ fn select_str < ' a > ( cond : bool , a : & ' a str , b : & ' a str ) -> & ' a str {
538+ if cond { a } else { b }
539+ }
540+
541+ struct MyRefStr < ' a > {
542+ ref_str : & ' a str ,
543+ }
544+
545+ pub fn test_lifetime_annotations ( ) {
546+ let str1: * const str ;
547+ {
548+ let foo = String :: from ( "foo" ) ;
549+ let bar = String :: from ( "bar" ) ;
550+ str1 = select_str ( true , foo. as_str ( ) , bar. as_str ( ) ) ;
551+
552+ unsafe {
553+ let v1 = & * str1; // GOOD
554+ println ! ( " v1 = {v1}" ) ;
555+ }
556+ } // (`foo`, `bar` go out of scope, the return value of `select_str` has the same lifetime, thus `str1` is dangling)
557+
558+ unsafe {
559+ let v2 = & * str1; // $ MISSING: Alert
560+ println ! ( " v2 = {v2} (!)" ) ; // corrupt in practice
561+ }
562+
563+ let my_ref;
564+ let str2: * const str ;
565+ {
566+ let baz = String :: from ( "baz" ) ;
567+ my_ref = MyRefStr { ref_str : baz. as_str ( ) } ;
568+ str2 = & * my_ref. ref_str ;
569+
570+ unsafe {
571+ let v3 = & * str2; // GOOD
572+ println ! ( " v3 = {v3}" ) ;
573+ }
574+ } // (`baz` goes out of scope, `ref_str` has the same lifetime, thus `str2` is dangling)
575+
576+ use_the_stack ( ) ;
577+
578+ unsafe {
579+ let v4 = & * str2; // $ MISSING: Alert
580+ println ! ( " v4 = {v4} (!)" ) ; // corrupt in practice
581+ }
582+ }
0 commit comments