12
12
// See the License for the specific language governing permissions and
13
13
// limitations under the License.
14
14
15
- pub struct AsOption < ' lt , T > ( pub & ' lt T ) ;
16
-
17
- impl < T > AsOption < ' _ , :: core:: option:: Option < T > > {
18
- #[ inline]
19
- // We need to allow for dead code at this point because
20
- // the Rust compiler thinks this function is unused even
21
- // though it acts as the specialized case for detection.
22
- #[ allow( dead_code) ]
23
- pub fn value ( & self ) -> Option < & T > {
24
- self . 0 . as_ref ( )
25
- }
26
- }
27
-
28
- impl < ' lt , T > AsOption < ' lt , & ' lt :: core:: option:: Option < T > > {
29
- #[ inline]
30
- pub fn value ( & self ) -> Option < & T > {
31
- self . 0 . as_ref ( )
32
- }
33
- }
34
-
35
- pub trait AsOptionFallback < T > {
36
- fn value ( & self ) -> Option < & T > ;
37
- }
38
- impl < T > AsOptionFallback < T > for AsOption < ' _ , T > {
39
- #[ inline]
40
- fn value ( & self ) -> Option < & T > {
41
- Some ( self . 0 )
42
- }
43
- }
44
15
45
16
/// Evaluates to `None` if the given expression is a `Option::None`.
46
17
///
@@ -50,10 +21,29 @@ impl<T> AsOptionFallback<T> for AsOption<'_, T> {
50
21
#[ macro_export]
51
22
#[ doc( hidden) ]
52
23
macro_rules! as_option {
53
- ( $e: expr $( , ) ? ) => { {
54
- #[ allow( unused_imports) ]
55
- use $crate:: option_info:: AsOptionFallback as _;
56
- $crate:: option_info:: AsOption ( & $e) . value( )
24
+ ( None $( , ) ?) => { { None } } ;
25
+ ( & None $( , ) ?) => { { None } } ;
26
+ ( Option :: <$t: ty>:: None $( , ) ?) => { {
27
+ None :: <& $t>
28
+ } } ;
29
+ ( & Option :: <$t: ty>:: None $( , ) ?) => { {
30
+ None :: <& $t>
31
+ } } ;
32
+
33
+ // Special case for Some literals
34
+ ( Some ( $val: expr) $( , ) ?) => { {
35
+ Some ( & $val)
36
+ } } ;
37
+ ( & Some ( $val: expr) $( , ) ?) => { {
38
+ Some ( & $val)
39
+ } } ;
40
+
41
+ ( & $local: expr $( , ) ? ) => { {
42
+ Some ( & $local)
43
+ } } ;
44
+
45
+ ( $local: expr $( , ) ? ) => { {
46
+ Some ( & $local)
57
47
} } ;
58
48
}
59
49
@@ -64,14 +54,70 @@ mod tests {
64
54
assert_eq ! ( Some ( & true ) , as_option!( true ) ) ;
65
55
assert_eq ! ( Some ( & 42 ) , as_option!( 42 ) ) ;
66
56
assert_eq ! ( Some ( & "Hello, World!" ) , as_option!( "Hello, World!" ) ) ;
67
-
57
+
68
58
assert_eq ! ( Some ( & ( ) ) , as_option!( Some ( ( ) ) ) ) ;
69
59
assert_eq ! ( Some ( & 5 ) , as_option!( Some ( 5 ) ) ) ;
70
60
assert_eq ! ( Some ( & true ) , as_option!( Some ( true ) ) ) ;
71
61
assert_eq ! ( Some ( & true ) , as_option!( & Some ( true ) ) ) ;
72
-
62
+
73
63
assert_eq ! ( None , as_option!( Option :: <u32 >:: None ) ) ;
74
64
assert_eq ! ( None , as_option!( Option :: <bool >:: None ) ) ;
75
65
assert_eq ! ( None , as_option!( & Option :: <bool >:: None ) ) ;
76
66
}
67
+
68
+ #[ test]
69
+ fn struct_fields_and_metadata_work ( ) {
70
+ struct TestStruct {
71
+ field_1 : u32 ,
72
+ field_2 : u64 ,
73
+ }
74
+
75
+ let test = TestStruct {
76
+ field_1 : 1 ,
77
+ field_2 : 2 ,
78
+ } ;
79
+
80
+ assert_eq ! ( Some ( & test. field_1) , as_option!( test. field_1) ) ;
81
+ assert_eq ! ( Some ( & test. field_1) , as_option!( & test. field_1) ) ;
82
+ assert_eq ! ( Some ( & test. field_2) , as_option!( test. field_2) ) ;
83
+ assert_eq ! ( Some ( & test. field_2) , as_option!( & test. field_2) ) ;
84
+
85
+ // This simulates the event_metadata.rs case that was failing
86
+ #[ derive( Debug ) ]
87
+ struct EventField {
88
+ value : u64 ,
89
+ }
90
+
91
+ // Test with temporary struct and field access - critical for Rust 2024
92
+ let field_ref = as_option ! ( EventField { value: 123 } . value) ;
93
+ assert_eq ! ( Some ( & 123 ) , field_ref) ;
94
+ }
95
+
96
+ #[ test]
97
+ fn event_stable_field_pattern_works ( ) {
98
+ // This test simulates the exact pattern used in the event macro
99
+ // where a field is bound to a variable and then wrapped in as_option
100
+
101
+ struct EventStruct {
102
+ field_1 : u32 ,
103
+ field_2 : u64 ,
104
+ }
105
+
106
+ let event = EventStruct {
107
+ field_1 : 42 ,
108
+ field_2 : 100 ,
109
+ } ;
110
+
111
+ // This is how fields are processed in the event macro:
112
+ let stable_field = event. field_1 ;
113
+ assert_eq ! ( Some ( & 42 ) , as_option!( stable_field) ) ;
114
+
115
+ // Test with normal field access
116
+ assert_eq ! ( Some ( & 100 ) , as_option!( event. field_2) ) ;
117
+
118
+ // Test with temporary values
119
+ let get_value = || 123 ;
120
+ let stable_field_2 = get_value ( ) ;
121
+ assert_eq ! ( Some ( & 123 ) , as_option!( stable_field_2) ) ;
122
+ }
77
123
}
0 commit comments