File tree Expand file tree Collapse file tree 6 files changed +126
-0
lines changed Expand file tree Collapse file tree 6 files changed +126
-0
lines changed Original file line number Diff line number Diff line change
1
+ [workspace ]
2
+ members = [
3
+ " derive_macros" ,
4
+ " use_macros" ,
5
+ ]
Original file line number Diff line number Diff line change
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
+ ```
Original file line number Diff line number Diff line change
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"
Original file line number Diff line number Diff line change
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
+ }
Original file line number Diff line number Diff line change
1
+ [package ]
2
+ name = " use_macros"
3
+ version = " 0.1.0"
4
+ edition = " 2021"
5
+
6
+ [dependencies ]
7
+ derive_macros = { path = " ../derive_macros" }
Original file line number Diff line number Diff line change
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
+ }
You can’t perform that action at this time.
0 commit comments