@@ -4,13 +4,12 @@ use std::cell::RefCell;
4
4
use std:: cmp:: { Ord , Ordering , PartialOrd } ;
5
5
use std:: collections:: HashMap ;
6
6
use std:: convert:: AsRef ;
7
- use std:: ffi:: OsStr ;
8
7
use std:: fmt;
9
8
use std:: hash:: { Hash , Hasher } ;
10
9
use std:: marker:: PhantomData ;
11
10
use std:: mem;
12
11
use std:: ops:: Deref ;
13
- use std:: path:: { Path , PathBuf } ;
12
+ use std:: path:: PathBuf ;
14
13
use std:: sync:: Mutex ;
15
14
16
15
// FIXME: replace with std::lazy after it gets stabilized and reaches beta
@@ -20,15 +19,9 @@ use crate::builder::Step;
20
19
21
20
pub struct Interned < T > ( usize , PhantomData < * const T > ) ;
22
21
23
- impl Default for Interned < String > {
22
+ impl < T : Internable + Default > Default for Interned < T > {
24
23
fn default ( ) -> Self {
25
- INTERNER . intern_string ( String :: default ( ) )
26
- }
27
- }
28
-
29
- impl Default for Interned < PathBuf > {
30
- fn default ( ) -> Self {
31
- INTERNER . intern_path ( PathBuf :: default ( ) )
24
+ T :: default ( ) . intern ( )
32
25
}
33
26
}
34
27
@@ -77,87 +70,48 @@ impl fmt::Display for Interned<String> {
77
70
}
78
71
}
79
72
80
- impl fmt:: Debug for Interned < String > {
81
- fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
82
- let s: & str = & * self ;
83
- f. write_fmt ( format_args ! ( "{:?}" , s) )
84
- }
85
- }
86
- impl fmt:: Debug for Interned < PathBuf > {
73
+ impl < T , U : ?Sized + fmt:: Debug > fmt:: Debug for Interned < T >
74
+ where
75
+ Self : Deref < Target = U > ,
76
+ {
87
77
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
88
- let s: & Path = & * self ;
78
+ let s: & U = & * self ;
89
79
f. write_fmt ( format_args ! ( "{:?}" , s) )
90
80
}
91
81
}
92
82
93
- impl Hash for Interned < String > {
83
+ impl < T : Internable + Hash > Hash for Interned < T > {
94
84
fn hash < H : Hasher > ( & self , state : & mut H ) {
95
- let l = INTERNER . strs . lock ( ) . unwrap ( ) ;
85
+ let l = T :: intern_cache ( ) . lock ( ) . unwrap ( ) ;
96
86
l. get ( * self ) . hash ( state)
97
87
}
98
88
}
99
89
100
- impl Hash for Interned < PathBuf > {
101
- fn hash < H : Hasher > ( & self , state : & mut H ) {
102
- let l = INTERNER . paths . lock ( ) . unwrap ( ) ;
103
- l. get ( * self ) . hash ( state)
104
- }
105
- }
106
-
107
- impl Deref for Interned < String > {
108
- type Target = str ;
109
- fn deref ( & self ) -> & ' static str {
110
- let l = INTERNER . strs . lock ( ) . unwrap ( ) ;
111
- unsafe { mem:: transmute :: < & str , & ' static str > ( l. get ( * self ) ) }
112
- }
113
- }
114
-
115
- impl Deref for Interned < PathBuf > {
116
- type Target = Path ;
117
- fn deref ( & self ) -> & ' static Path {
118
- let l = INTERNER . paths . lock ( ) . unwrap ( ) ;
119
- unsafe { mem:: transmute :: < & Path , & ' static Path > ( l. get ( * self ) ) }
120
- }
121
- }
122
-
123
- impl AsRef < Path > for Interned < PathBuf > {
124
- fn as_ref ( & self ) -> & ' static Path {
125
- let l = INTERNER . paths . lock ( ) . unwrap ( ) ;
126
- unsafe { mem:: transmute :: < & Path , & ' static Path > ( l. get ( * self ) ) }
127
- }
128
- }
129
-
130
- impl AsRef < Path > for Interned < String > {
131
- fn as_ref ( & self ) -> & ' static Path {
132
- let l = INTERNER . strs . lock ( ) . unwrap ( ) ;
133
- unsafe { mem:: transmute :: < & Path , & ' static Path > ( l. get ( * self ) . as_ref ( ) ) }
90
+ impl < T : Internable + Deref > Deref for Interned < T > {
91
+ type Target = T :: Target ;
92
+ fn deref ( & self ) -> & ' static Self :: Target {
93
+ let l = T :: intern_cache ( ) . lock ( ) . unwrap ( ) ;
94
+ unsafe { mem:: transmute :: < & Self :: Target , & ' static Self :: Target > ( l. get ( * self ) ) }
134
95
}
135
96
}
136
97
137
- impl AsRef < OsStr > for Interned < PathBuf > {
138
- fn as_ref ( & self ) -> & ' static OsStr {
139
- let l = INTERNER . paths . lock ( ) . unwrap ( ) ;
140
- unsafe { mem:: transmute :: < & OsStr , & ' static OsStr > ( l. get ( * self ) . as_ref ( ) ) }
98
+ impl < T : Internable + AsRef < U > , U : ? Sized > AsRef < U > for Interned < T > {
99
+ fn as_ref ( & self ) -> & ' static U {
100
+ let l = T :: intern_cache ( ) . lock ( ) . unwrap ( ) ;
101
+ unsafe { mem:: transmute :: < & U , & ' static U > ( l. get ( * self ) . as_ref ( ) ) }
141
102
}
142
103
}
143
104
144
- impl AsRef < OsStr > for Interned < String > {
145
- fn as_ref ( & self ) -> & ' static OsStr {
146
- let l = INTERNER . strs . lock ( ) . unwrap ( ) ;
147
- unsafe { mem:: transmute :: < & OsStr , & ' static OsStr > ( l. get ( * self ) . as_ref ( ) ) }
148
- }
149
- }
150
-
151
- impl PartialOrd < Interned < String > > for Interned < String > {
105
+ impl < T : Internable + PartialOrd > PartialOrd for Interned < T > {
152
106
fn partial_cmp ( & self , other : & Self ) -> Option < Ordering > {
153
- let l = INTERNER . strs . lock ( ) . unwrap ( ) ;
107
+ let l = T :: intern_cache ( ) . lock ( ) . unwrap ( ) ;
154
108
l. get ( * self ) . partial_cmp ( l. get ( * other) )
155
109
}
156
110
}
157
111
158
- impl Ord for Interned < String > {
112
+ impl < T : Internable + Ord > Ord for Interned < T > {
159
113
fn cmp ( & self , other : & Self ) -> Ordering {
160
- let l = INTERNER . strs . lock ( ) . unwrap ( ) ;
114
+ let l = T :: intern_cache ( ) . lock ( ) . unwrap ( ) ;
161
115
l. get ( * self ) . cmp ( l. get ( * other) )
162
116
}
163
117
}
@@ -210,6 +164,26 @@ pub struct Interner {
210
164
paths : Mutex < TyIntern < PathBuf > > ,
211
165
}
212
166
167
+ trait Internable : Clone + Eq + Hash + ' static {
168
+ fn intern_cache ( ) -> & ' static Mutex < TyIntern < Self > > ;
169
+
170
+ fn intern ( self ) -> Interned < Self > {
171
+ Self :: intern_cache ( ) . lock ( ) . unwrap ( ) . intern ( self )
172
+ }
173
+ }
174
+
175
+ impl Internable for String {
176
+ fn intern_cache ( ) -> & ' static Mutex < TyIntern < Self > > {
177
+ & INTERNER . strs
178
+ }
179
+ }
180
+
181
+ impl Internable for PathBuf {
182
+ fn intern_cache ( ) -> & ' static Mutex < TyIntern < Self > > {
183
+ & INTERNER . paths
184
+ }
185
+ }
186
+
213
187
impl Interner {
214
188
pub fn intern_str ( & self , s : & str ) -> Interned < String > {
215
189
self . strs . lock ( ) . unwrap ( ) . intern_borrow ( s)
0 commit comments