@@ -4,13 +4,12 @@ use std::cell::RefCell;
44use std:: cmp:: { Ord , Ordering , PartialOrd } ;
55use std:: collections:: HashMap ;
66use std:: convert:: AsRef ;
7- use std:: ffi:: OsStr ;
87use std:: fmt;
98use std:: hash:: { Hash , Hasher } ;
109use std:: marker:: PhantomData ;
1110use std:: mem;
1211use std:: ops:: Deref ;
13- use std:: path:: { Path , PathBuf } ;
12+ use std:: path:: PathBuf ;
1413use std:: sync:: Mutex ;
1514
1615// FIXME: replace with std::lazy after it gets stabilized and reaches beta
@@ -20,15 +19,9 @@ use crate::builder::Step;
2019
2120pub struct Interned < T > ( usize , PhantomData < * const T > ) ;
2221
23- impl Default for Interned < String > {
22+ impl < T : Internable + Default > Default for Interned < T > {
2423 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 ( )
3225 }
3326}
3427
@@ -77,87 +70,48 @@ impl fmt::Display for Interned<String> {
7770 }
7871}
7972
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+ {
8777 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
88- let s: & Path = & * self ;
78+ let s: & U = & * self ;
8979 f. write_fmt ( format_args ! ( "{:?}" , s) )
9080 }
9181}
9282
93- impl Hash for Interned < String > {
83+ impl < T : Internable + Hash > Hash for Interned < T > {
9484 fn hash < H : Hasher > ( & self , state : & mut H ) {
95- let l = INTERNER . strs . lock ( ) . unwrap ( ) ;
85+ let l = T :: intern_cache ( ) . lock ( ) . unwrap ( ) ;
9686 l. get ( * self ) . hash ( state)
9787 }
9888}
9989
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 ) ) }
13495 }
13596}
13697
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 ( ) ) }
141102 }
142103}
143104
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 > {
152106 fn partial_cmp ( & self , other : & Self ) -> Option < Ordering > {
153- let l = INTERNER . strs . lock ( ) . unwrap ( ) ;
107+ let l = T :: intern_cache ( ) . lock ( ) . unwrap ( ) ;
154108 l. get ( * self ) . partial_cmp ( l. get ( * other) )
155109 }
156110}
157111
158- impl Ord for Interned < String > {
112+ impl < T : Internable + Ord > Ord for Interned < T > {
159113 fn cmp ( & self , other : & Self ) -> Ordering {
160- let l = INTERNER . strs . lock ( ) . unwrap ( ) ;
114+ let l = T :: intern_cache ( ) . lock ( ) . unwrap ( ) ;
161115 l. get ( * self ) . cmp ( l. get ( * other) )
162116 }
163117}
@@ -210,6 +164,26 @@ pub struct Interner {
210164 paths : Mutex < TyIntern < PathBuf > > ,
211165}
212166
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+
213187impl Interner {
214188 pub fn intern_str ( & self , s : & str ) -> Interned < String > {
215189 self . strs . lock ( ) . unwrap ( ) . intern_borrow ( s)
0 commit comments