Skip to content

Commit 24fb82b

Browse files
0.0.1-alpha: unsafe_method! rust:1.54.0-alpine Docker in GitHub Actions
1 parent 32b0555 commit 24fb82b

File tree

2 files changed

+123
-34
lines changed

2 files changed

+123
-34
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22

33
# 0.0.1-alpha
44

5-
Initial. Only `unsafe_call!` macro.
5+
Initial. Only `unsafe_fn!` and `unsafe_method!` macros.

src/lib.rs

Lines changed: 122 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,26 @@
11
#![doc = include_str!("../README.md")]
22
#![cfg_attr(not(any(doc, test)), no_std)]
3+
// This only refuses unsafe code in functions/expressions in this crate, not ones generated by this
4+
// crate's macros.
35
#![cfg_attr(not(any(doc, test)), forbid(unsafe_code))]
46
//#[cfg(doc)]
57
//extern crate alloc;
68

9+
/// Invoke am unsafe function.
710
#[macro_export]
8-
macro_rules! unsafe_method {
9-
($self:expr, $fn:expr $(, $arg:expr)+ ) => {
10-
};
11-
}
12-
13-
#[macro_export]
14-
macro_rules! unsafe_call {
15-
($fn:expr $(, $arg:expr)+ ) => {
16-
// Enclosed in a block, so the result can be used as a value in an outer expression.
11+
macro_rules! unsafe_fn {
12+
( $fn:expr $(, $arg:expr)+ ) => {
13+
// Enclosed in a block, so that
14+
// 1. the result can be used as a value in an outer expression,and
15+
// 2. local variables don't conflict with the outer scope
1716
{
18-
let tuple = $crate::unsafe_call!{~ $($arg),* };
19-
unsafe {
20-
$crate::unsafe_call! {~~
21-
$fn,
22-
tuple,
23-
( $( $arg ),* ),
24-
(0)
25-
}
17+
let tuple = $crate::unsafe_fn!{~~ $($arg),* };
18+
let fun = $fn;
19+
$crate::unsafe_fn! {~~~
20+
fun,
21+
tuple,
22+
( $( $arg ),* ),
23+
(0)
2624
}
2725
}
2826
};
@@ -31,24 +29,26 @@ macro_rules! unsafe_call {
3129
};
3230

3331
// Construct the tuple:
34-
(~ $first:expr, $($rest:expr),+ ) => {
32+
(~~ $first:expr, $($rest:expr),+ ) => {
3533
(
36-
$first, $crate::unsafe_call!{ ~ $($rest),+ }
34+
$first, $crate::unsafe_fn!{ ~~ $($rest),+ }
3735
)
3836
};
39-
(~ $last:expr) => {
37+
(~~ $last:expr) => {
4038
($last,)
4139
};
4240
// Commented out: For now, we require the (potentially unsafe) function to have at least 1 argument.
4341
//
44-
//(~) => { () };
42+
//(~~) => { () };
4543

4644
// Access tuple parts and call the function:
47-
(~~ $fn:expr, $tuple:ident,
45+
(~~~ $fn:expr, $tuple:ident,
4846
( $_first_arg:expr, $($other_arg:expr),+ ),
49-
$( ( $($accessor_part:tt),+ ) ),*
47+
$( ( $($accessor_part:tt),+
48+
)
49+
),*
5050
) => {
51-
$crate::unsafe_call!{ ~~
51+
$crate::unsafe_fn!{ ~~~
5252
$fn, $tuple, ( $($other_arg),+ ),
5353
// Insert a new accessor to front (left): 0.
5454
(0),
@@ -57,23 +57,85 @@ macro_rules! unsafe_call {
5757
),*
5858
}
5959
};
60-
(~~ $fn:expr, $tuple:ident,
60+
// All accessors are ready, so call the function:
61+
(~~~ $fn:expr, $tuple:ident,
6162
( $_last_or_only_arg:expr ),
6263
$( ( $($accessor_part:tt),+
6364
)
6465
),*
6566
) => {
66-
$fn( $(
67-
$crate::unsafe_call!{ ~~~ $tuple, $($accessor_part),+ }
68-
),*
69-
)
67+
unsafe {
68+
$fn( $(
69+
$crate::unsafe_fn!{ ~~~~ $tuple, $($accessor_part),+ }
70+
),*
71+
)
72+
}
7073
};
7174

7275
// Expand an accessor group/list to access a field in the tuple:
73-
(~~~ $tuple:ident, $($accessor_part:tt),* ) => {
76+
(~~~~ $tuple:ident, $($accessor_part:tt),* ) => {
7477
$tuple $(. $accessor_part )*
7578
};
7679
}
80+
//-------------
81+
82+
/// Invoke am unsafe method. Like [unsafe_fn], but
83+
/// - we accept a receiver `self`
84+
/// - we store `self` in a variable outside of the generated `unsafe {...}`
85+
/// - we don't allow $fn to be an expression (which doesn't work in standard methods calls), but
86+
/// only an identifier.
87+
#[macro_export]
88+
macro_rules! unsafe_method {
89+
($self:expr, $fn:ident $(, $arg:expr)+ ) => {
90+
// Enclosed in a block, so that
91+
// 1. the result can be used as a value in an outer expression,and
92+
// 2. local variables don't conflict with the outer scope
93+
{
94+
let tuple = $crate::unsafe_fn!{~~ $($arg),* }; // re-using unsafe_fn
95+
let receiver = $self;
96+
$crate::unsafe_method! {~~~
97+
receiver,
98+
$fn,
99+
tuple,
100+
( $( $arg ),* ),
101+
(0)
102+
}
103+
}
104+
};
105+
106+
// Access tuple parts and call the function:
107+
(~~~ $self:expr, $fn:ident, $tuple:ident,
108+
( $_first_arg:expr, $($other_arg:expr),+ ),
109+
$( ( $($accessor_part:tt),+
110+
)
111+
),*
112+
) => {
113+
$crate::unsafe_method!{ ~~~
114+
$self, $fn, $tuple, ( $($other_arg),+ ),
115+
// Insert a new accessor to front (left): 0.
116+
(0),
117+
$( // Prepend 1 to each supplied/existing accessor
118+
( 1, $($accessor_part),+ )
119+
),*
120+
}
121+
};
122+
// All accessors are ready, so call the function:
123+
(~~~ $self:expr, $fn:ident, $tuple:ident,
124+
( $_last_or_only_arg:expr ),
125+
$( ( $($accessor_part:tt),+
126+
)
127+
),*
128+
) => {
129+
unsafe {
130+
$self. $fn( $(
131+
$crate::unsafe_fn!{ ~~~~ $tuple, $($accessor_part),+ }
132+
),*
133+
)
134+
}
135+
};
136+
}
137+
138+
//-------------
77139

78140
#[cfg(test)]
79141
mod tests {
@@ -83,16 +145,43 @@ mod tests {
83145

84146
#[test]
85147
fn it_works() {
86-
//let tuple = unsafe_call!{~ 'c', true, 1, -5 };
87-
unsafe_call!(unsafe_a, 'c', true, 1, -5);
148+
//let tuple = unsafe_fn!{~~ 'c', true, 1, -5 };
149+
unsafe_fn!(unsafe_a, 'c', true, 1, -5);
88150

89151
//unsafe fn f() {}
90-
//unsafe_call!( f);
152+
//unsafe_fn!( f);
91153

92154
/*let args = ('c', (true, (1, (0,))));
93155
unsafe {
94156
let _ = unsafe_a(args.0, args.1.0, args.1.1.0, args.1.1.1.0);
95157
}
96158
*/
159+
160+
let _ = unsafe_fn!(usize::unchecked_add, 1, 1);
161+
let _ = unsafe_method!(1u8, unchecked_add, 0);
162+
let _ = unsafe { 1_u8.unchecked_add(0) };
163+
}
164+
}
165+
166+
// @TODO move to docs/tests
167+
#[allow(unused)]
168+
mod always_test {
169+
fn f(i: usize) -> usize {
170+
i + 1
171+
}
172+
173+
fn g() -> fn(usize) -> usize {
174+
f
175+
}
176+
177+
pub fn store_function_name() {
178+
let fun = f;
179+
f(0);
180+
181+
let fun = g;
182+
fun()(1);
183+
184+
let fun = usize::wrapping_add;
185+
fun(1, 0);
97186
}
98187
}

0 commit comments

Comments
 (0)