@@ -2,7 +2,6 @@ mod synthesis;
2
2
3
3
use proc_macro2:: { Span , TokenStream } ;
4
4
use quote:: quote;
5
- use self_cell:: self_cell;
6
5
use spdlog_internal:: pattern_parser:: {
7
6
check_custom_pattern_names, parse:: Template , PatternRegistry , Result ,
8
7
} ;
@@ -71,26 +70,18 @@ pub fn runtime_pattern_impl(runtime_pattern: RuntimePattern) -> Result<TokenStre
71
70
72
71
pub struct Pattern {
73
72
/// The template string included in the pattern.
74
- template : TemplateSelfRef ,
73
+ template : Option < ( & ' static String , Template < ' static > ) > ,
75
74
/// Any user-provided pattern-to-formatter mapping.
76
75
custom_patterns : CustomPatterns ,
77
76
}
78
77
79
- self_cell ! {
80
- pub struct TemplateSelfRef {
81
- owner: String ,
82
- #[ covariant]
83
- dependent: Template ,
84
- }
85
- }
86
-
87
78
impl Pattern {
88
79
fn custom_patterns ( & self ) -> impl IntoIterator < Item = & ( Ident , Path ) > {
89
80
self . custom_patterns . 0 . iter ( )
90
81
}
91
82
92
83
fn template ( & self ) -> & Template {
93
- self . template . borrow_dependent ( )
84
+ & self . template . as_ref ( ) . unwrap ( ) . 1
94
85
}
95
86
}
96
87
@@ -100,20 +91,33 @@ impl Parse for Pattern {
100
91
input. parse :: < Option < Token ! [ , ] > > ( ) ?;
101
92
let custom_patterns = input. parse ( ) ?;
102
93
103
- let ret = Pattern {
104
- template : TemplateSelfRef :: try_new ( template_lit. value ( ) , |template_str| {
105
- Template :: parse ( template_str) . map_err ( |err| {
106
- syn:: Error :: new (
107
- // TODO: Maybe we can make a subspan for the literal for a better error
108
- // message
109
- template_lit. span ( ) ,
110
- err,
111
- )
112
- } )
113
- } ) ?,
94
+ // Struct `Template` have almost no way of owning a `String`, we have to store
95
+ // `template_lit` somewhere. Here we use `Box::leak` + `Box::from_raw` to create
96
+ // a simple self-reference.
97
+ let template_lit_leaked = Box :: leak ( Box :: new ( template_lit. value ( ) ) ) ;
98
+
99
+ let template = Template :: parse ( template_lit_leaked) . map_err ( |err| {
100
+ syn:: Error :: new (
101
+ // TODO: Maybe we can make a subspan for the literal for a better error message
102
+ template_lit. span ( ) ,
103
+ err,
104
+ )
105
+ } ) ?;
106
+
107
+ Ok ( Pattern {
108
+ template : Some ( ( template_lit_leaked, template) ) ,
114
109
custom_patterns,
115
- } ;
116
- Ok ( ret)
110
+ } )
111
+ }
112
+ }
113
+
114
+ impl Drop for Pattern {
115
+ fn drop ( & mut self ) {
116
+ let ( template_lit_leaked, template) = self . template . take ( ) . unwrap ( ) ;
117
+ // Drop the user of the leaked data first.
118
+ drop ( template) ;
119
+ // Restore the ownership of the leaked `String` and then drop it.
120
+ drop ( unsafe { Box :: from_raw ( template_lit_leaked as * const String as * mut String ) } ) ;
117
121
}
118
122
}
119
123
0 commit comments