@@ -2,7 +2,7 @@ use crate::{
22 builtins:: { PyStr , PyTypeRef } ,
33 common:: lock:: PyRwLock ,
44 convert:: ToPyObject ,
5- Py , PyExact , PyObject , PyObjectRef , PyRef , PyRefExact ,
5+ AsObject , Py , PyExact , PyObject , PyObjectRef , PyRef , PyRefExact ,
66} ;
77use std:: {
88 borrow:: { Borrow , ToOwned } ,
@@ -43,14 +43,17 @@ impl StringPool {
4343 let inserted = zelf. inner . write ( ) . insert ( cache. clone ( ) ) ;
4444 if inserted {
4545 let interned = unsafe { PyStrInterned :: borrow_cache ( & cache) } ;
46- // unsafe { interned.as_object().mark_intern() };
46+ unsafe { interned. as_object ( ) . mark_intern ( ) } ;
4747 interned
4848 } else {
49- zelf. inner
50- . read ( )
51- . get ( cache. as_str ( ) )
52- . map ( |cached| unsafe { PyStrInterned :: borrow_cache ( cached) } )
53- . expect ( "" )
49+ unsafe {
50+ PyStrInterned :: borrow_cache (
51+ zelf. inner
52+ . read ( )
53+ . get ( cache. as_ref ( ) )
54+ . expect ( "inserted is false" ) ,
55+ )
56+ }
5457 }
5558 }
5659 let str_ref = s. into_pyref_exact ( typ) ;
@@ -152,18 +155,20 @@ impl Borrow<PyObject> for PyStrInterned {
152155 }
153156}
154157
155- impl Deref for PyStrInterned {
156- type Target = Py < PyStr > ;
158+ // NOTE: std::hash::Hash of Self and Self::Borrowed *must* be the same
159+ // This is ok only because PyObject doesn't implement Hash
160+ impl std:: hash:: Hash for PyStrInterned {
157161 #[ inline( always) ]
158- fn deref ( & self ) -> & Self :: Target {
159- & self . inner
162+ fn hash < H : std :: hash :: Hasher > ( & self , state : & mut H ) {
163+ self . get_id ( ) . hash ( state )
160164 }
161165}
162166
163- impl std:: hash:: Hash for PyStrInterned {
167+ impl Deref for PyStrInterned {
168+ type Target = Py < PyStr > ;
164169 #[ inline( always) ]
165- fn hash < H : std :: hash :: Hasher > ( & self , state : & mut H ) {
166- std :: hash :: Hash :: hash ( & ( self as * const _ ) , state )
170+ fn deref ( & self ) -> & Self :: Target {
171+ & self . inner
167172 }
168173}
169174
@@ -177,7 +182,7 @@ impl PartialEq for PyStrInterned {
177182impl Eq for PyStrInterned { }
178183
179184impl AsRef < str > for PyStrInterned {
180- #[ inline]
185+ #[ inline( always ) ]
181186 fn as_ref ( & self ) -> & str {
182187 self . as_str ( )
183188 }
@@ -216,8 +221,12 @@ mod sealed {
216221}
217222
218223/// A sealed marker trait for `DictKey` types that always become an exact instance of `str`
219- pub trait Internable : sealed:: SealedInternable + ToPyObject + AsRef < Self :: Interned > {
220- type Interned : ?Sized + MaybeInterned ;
224+ pub trait Internable
225+ where
226+ Self : sealed:: SealedInternable + ToPyObject + AsRef < Self :: Interned > ,
227+ Self :: Interned : MaybeInterned ,
228+ {
229+ type Interned : ?Sized ;
221230 fn into_pyref_exact ( self , str_type : PyTypeRef ) -> PyRefExact < PyStr > ;
222231}
223232
@@ -269,6 +278,24 @@ impl MaybeInterned for PyExact<PyStr> {
269278impl MaybeInterned for Py < PyStr > {
270279 #[ inline( always) ]
271280 fn as_interned ( & self ) -> Option < & ' static PyStrInterned > {
272- None
281+ if self . as_object ( ) . is_interned ( ) {
282+ Some ( unsafe { std:: mem:: transmute ( self ) } )
283+ } else {
284+ None
285+ }
286+ }
287+ }
288+
289+ impl PyObject {
290+ #[ inline]
291+ pub fn as_interned_str ( & self , vm : & crate :: VirtualMachine ) -> Option < & ' static PyStrInterned > {
292+ let s: Option < & Py < PyStr > > = self . downcast_ref ( ) ;
293+ if self . is_interned ( ) {
294+ s. unwrap ( ) . as_interned ( )
295+ } else if let Some ( s) = s {
296+ vm. ctx . interned_str ( s. as_str ( ) )
297+ } else {
298+ None
299+ }
273300 }
274301}
0 commit comments