Skip to content

Commit 041a473

Browse files
committed
fix: as_option macro
1 parent 8e02483 commit 041a473

File tree

1 file changed

+81
-35
lines changed

1 file changed

+81
-35
lines changed

crates/ink/src/option_info.rs

+81-35
Original file line numberDiff line numberDiff line change
@@ -12,35 +12,6 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

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-
}
4415

4516
/// Evaluates to `None` if the given expression is a `Option::None`.
4617
///
@@ -50,10 +21,29 @@ impl<T> AsOptionFallback<T> for AsOption<'_, T> {
5021
#[macro_export]
5122
#[doc(hidden)]
5223
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)
5747
}};
5848
}
5949

@@ -64,14 +54,70 @@ mod tests {
6454
assert_eq!(Some(&true), as_option!(true));
6555
assert_eq!(Some(&42), as_option!(42));
6656
assert_eq!(Some(&"Hello, World!"), as_option!("Hello, World!"));
67-
57+
6858
assert_eq!(Some(&()), as_option!(Some(())));
6959
assert_eq!(Some(&5), as_option!(Some(5)));
7060
assert_eq!(Some(&true), as_option!(Some(true)));
7161
assert_eq!(Some(&true), as_option!(&Some(true)));
72-
62+
7363
assert_eq!(None, as_option!(Option::<u32>::None));
7464
assert_eq!(None, as_option!(Option::<bool>::None));
7565
assert_eq!(None, as_option!(&Option::<bool>::None));
7666
}
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+
}
77123
}

0 commit comments

Comments
 (0)