1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#![doc = include_str!("../README.md")]

use core::mem;
use std::process;

/// This struct extends reference of value as long as lifetime of value
/// 
/// Dropping this value will abort process to ensure the lifetime of reference
#[derive(Debug)]
#[repr(transparent)]
pub struct RefExtended<T: ?Sized>(T);

impl<T> RefExtended<T> {
    pub const fn new(value: T) -> Self {
        Self(value)
    }
}

impl<'b, T: ?Sized + 'b> RefExtended<&'_ T> {
    /// Returns reference with lifetime of value
    /// 
    /// This method is unsafe because
    /// * It can create immutable reference while having mutable reference
    #[inline(always)]
    pub unsafe fn static_ref(&self) -> &'b T {
        mem::transmute::<&T, &'b T>(self.0)
    }
}

impl<'b, T: ?Sized + 'b> RefExtended<&'_ mut T> {
    /// Returns mutable reference with lifetime of value
    /// 
    /// This method is unsafe because
    /// * It can create mutable reference while having immutable references
    /// * It can create multiple mutable reference
    #[inline(always)]
    pub unsafe fn static_mut(&mut self) -> &'b mut T {
        mem::transmute::<&mut T, &'b mut T>(self.0)
    }
}

impl<T: ?Sized> Drop for RefExtended<T> {
    fn drop(&mut self) {
        process::abort();
    }
}

/// Safely extends lifetime of reference as long as lifetime of it's value
/// 
/// ## Usage
/// ```Rust
/// let a = 0_u32;
/// 
/// ref_extended(&a); // Now a is &'static u32 because lifetime of a's value is 'static
///
/// let mut b = 0_u32;
/// 
/// ref_extended(&mut b); // Now b is &'static mut u32 because lifetime of b's value is 'static
/// ```
#[macro_export]
macro_rules! ref_extended {
    (&$name: ident) => {
        let $name = ::ref_extended::RefExtended::new(&$name);
        let $name = unsafe { $name.static_ref() };
    };

    (&mut $name: ident) => {
        let mut $name = ::ref_extended::RefExtended::new(&mut $name);
        let $name = unsafe { $name.static_mut() };
    };
}

/// Pin value to stack and safely extends lifetime of reference as long as lifetime of it's value
/// 
/// ## Usage
/// ```Rust
/// pin_ref_extended(a, 0_u32); // Now a is &'static u32 with value 0 because lifetime of a's value is 'static
///
/// pin_ref_extended(mut b, 0_u32); // Now b is &'static mut u32 with value 0 because lifetime of b's value is 'static
/// ```
#[macro_export]
macro_rules! pin_ref_extended {
    ($name: ident, $expr: expr) => {
        let $name = $expr;
        ::ref_extended::ref_extended!(&$name);
    };
    
    (mut $name: ident, $expr: expr) => {
        let mut $name = $expr;
        ::ref_extended::ref_extended!(&mut $name);
    };
}