Skip to content

Commit 41f5618

Browse files
chore: add an example for rust derive trait order (#24)
1 parent e1a97f6 commit 41f5618

File tree

6 files changed

+126
-0
lines changed

6 files changed

+126
-0
lines changed

research/derive_order/Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[workspace]
2+
members = [
3+
"derive_macros",
4+
"use_macros",
5+
]

research/derive_order/README.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# Rust Derive Order Example
2+
3+
This project shows how the order of Rust derive traits can impact a struct's behavior.
4+
It includes two custom procedural macros `First` and `Second`.
5+
6+
## Structure
7+
8+
- **derive_macros/**: Defines the `First` and `Second` macros
9+
- **use_macros/**: Contains tests to verify the behavior of the macros
10+
11+
## Tests
12+
13+
Two tests demonstrate the importance of derive order:
14+
15+
1. **`test_first_second`**: `First` is derived before `Second`. This should pass.
16+
2. **`test_second_first`**: `Second` is derived before `First`. This may fail, but it actually passes. **Seems like the derive order does not matter!**
17+
18+
### Run Tests
19+
20+
To run the tests:
21+
22+
```shell
23+
cargo test -p use_macros -- --nocapture
24+
```
25+
26+
Output:
27+
28+
```shell
29+
running 2 tests
30+
First is implemented, so Second works!
31+
First is implemented, so Second works!
32+
test tests::test_second_first ... ok
33+
test tests::test_first_second ... ok
34+
```
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
[package]
2+
name = "derive_macros"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
[lib]
7+
proc-macro = true
8+
9+
[dependencies]
10+
proc-macro2 = "1.0"
11+
quote = "1.0"
12+
syn = "2.0"
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
extern crate proc_macro;
2+
use proc_macro::TokenStream;
3+
use quote::quote;
4+
use syn::{parse_macro_input, DeriveInput};
5+
6+
#[proc_macro_derive(First)]
7+
pub fn derive_first(input: TokenStream) -> TokenStream {
8+
let name = parse_macro_input!(input as DeriveInput).ident;
9+
10+
TokenStream::from(quote! {
11+
impl First for #name {
12+
fn is_first_implemented() -> bool {
13+
true
14+
}
15+
}
16+
})
17+
}
18+
19+
#[proc_macro_derive(Second)]
20+
pub fn derive_second(input: TokenStream) -> TokenStream {
21+
let name = parse_macro_input!(input as DeriveInput).ident;
22+
23+
TokenStream::from(quote! {
24+
impl Second for #name {
25+
fn check_first_is_implemented() -> bool {
26+
let result = <#name as First>::is_first_implemented();
27+
println!(
28+
"First is {}implemented, so Second {}!",
29+
if result { "" } else { "NOT " },
30+
if result { "works" } else { "fails" }
31+
);
32+
result
33+
}
34+
}
35+
})
36+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[package]
2+
name = "use_macros"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
[dependencies]
7+
derive_macros = { path = "../derive_macros" }
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// This test file checks if the order of Rust derive traits matters.
2+
// Since the keepsorted tool could reorder these traits in CI, we must ignore this file.
3+
// keepsorted: ignore file
4+
5+
#[cfg(test)]
6+
mod tests {
7+
use derive_macros::{First, Second};
8+
9+
trait First {
10+
fn is_first_implemented() -> bool;
11+
}
12+
13+
trait Second {
14+
fn check_first_is_implemented() -> bool;
15+
}
16+
17+
#[test]
18+
fn test_first_second() {
19+
#[derive(First, Second)] // <- This order should work.
20+
struct MyStruct;
21+
22+
assert!(MyStruct::check_first_is_implemented());
23+
}
24+
25+
#[test]
26+
fn test_second_first() {
27+
#[derive(Second, First)] // <- This order might not work.
28+
struct MyStruct;
29+
30+
assert!(MyStruct::check_first_is_implemented());
31+
}
32+
}

0 commit comments

Comments
 (0)