Skip to content

Commit bbc3136

Browse files
committed
PyInterned
1 parent 370b2b3 commit bbc3136

File tree

7 files changed

+58
-42
lines changed

7 files changed

+58
-42
lines changed

stdlib/src/array.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -683,7 +683,7 @@ mod array {
683683
fn typecode(&self, vm: &VirtualMachine) -> PyStrRef {
684684
vm.ctx
685685
.intern_str(self.read().typecode().to_string())
686-
.to_str()
686+
.to_owned()
687687
}
688688

689689
#[pyproperty]

vm/src/builtins/bool.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,6 @@ impl PyBool {
117117
vm.ctx.false_str
118118
}
119119
.to_owned()
120-
.into_pyref()
121120
}
122121

123122
#[pymethod(magic)]

vm/src/builtins/code.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ impl ConstantBag for PyObjBag<'_> {
104104
}
105105

106106
fn make_name(&self, name: &str) -> PyStrRef {
107-
self.0.intern_str(name).to_str()
107+
self.0.intern_str(name).to_owned()
108108
}
109109
}
110110

vm/src/builtins/str.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ impl IntoPyStrRef for &str {
230230
impl IntoPyStrRef for &'static crate::intern::PyStrInterned {
231231
#[inline]
232232
fn into_pystr_ref(self, _vm: &VirtualMachine) -> PyRef<PyStr> {
233-
self.to_str()
233+
self.to_owned()
234234
}
235235
}
236236

vm/src/intern.rs

Lines changed: 51 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use crate::{
22
builtins::{PyStr, PyTypeRef},
33
common::lock::PyRwLock,
44
convert::ToPyObject,
5-
AsObject, Py, PyExact, PyObject, PyObjectRef, PyRef, PyRefExact,
5+
AsObject, Py, PyExact, PyObject, PyObjectRef, PyPayload, PyRef, PyRefExact, VirtualMachine,
66
};
77
use std::{
88
borrow::{Borrow, ToOwned},
@@ -113,42 +113,36 @@ impl CachedPyStrRef {
113113
}
114114
}
115115

116-
/// The unique reference of interned PyStr
117-
/// Always intended to be used as a static reference
118-
pub struct PyStrInterned {
119-
inner: Py<PyStr>,
116+
pub struct PyInterned<T>
117+
where
118+
T: PyPayload,
119+
{
120+
inner: Py<T>,
120121
}
121122

122-
impl PyStrInterned {
123-
/// # Safety
124-
/// the given cache must be alive while returned reference is alive
123+
impl<T: PyPayload> PyInterned<T> {
125124
#[inline]
126-
unsafe fn borrow_cache(cache: &CachedPyStrRef) -> &'static Self {
127-
std::mem::transmute_copy(cache)
125+
pub fn leak(cache: PyRef<T>) -> &'static Self {
126+
unsafe { std::mem::transmute(cache) }
128127
}
129128

130129
#[inline]
131-
fn as_ptr(&self) -> *const Py<PyStr> {
130+
fn as_ptr(&self) -> *const Py<T> {
132131
self as *const _ as *const _
133132
}
134133

135134
#[inline]
136-
pub fn to_owned(&'static self) -> PyRefExact<PyStr> {
137-
unsafe { (*(&self as *const _ as *const PyRefExact<PyStr>)).clone() }
138-
}
139-
140-
#[inline]
141-
pub fn to_str(&'static self) -> PyRef<PyStr> {
142-
self.to_owned().into_pyref()
135+
pub fn to_owned(&'static self) -> PyRef<T> {
136+
unsafe { (*(&self as *const _ as *const PyRef<T>)).clone() }
143137
}
144138

145139
#[inline]
146140
pub fn to_object(&'static self) -> PyObjectRef {
147-
self.to_str().into()
141+
self.to_owned().into()
148142
}
149143
}
150144

151-
impl Borrow<PyObject> for PyStrInterned {
145+
impl<T: PyPayload> Borrow<PyObject> for PyInterned<T> {
152146
#[inline(always)]
153147
fn borrow(&self) -> &PyObject {
154148
self.inner.borrow()
@@ -157,41 +151,58 @@ impl Borrow<PyObject> for PyStrInterned {
157151

158152
// NOTE: std::hash::Hash of Self and Self::Borrowed *must* be the same
159153
// This is ok only because PyObject doesn't implement Hash
160-
impl std::hash::Hash for PyStrInterned {
154+
impl<T: PyPayload> std::hash::Hash for PyInterned<T> {
161155
#[inline(always)]
162156
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
163157
self.get_id().hash(state)
164158
}
165159
}
166160

167-
impl Deref for PyStrInterned {
168-
type Target = Py<PyStr>;
161+
impl<T: PyPayload> Deref for PyInterned<T> {
162+
type Target = Py<T>;
169163
#[inline(always)]
170164
fn deref(&self) -> &Self::Target {
171165
&self.inner
172166
}
173167
}
174168

175-
impl PartialEq for PyStrInterned {
169+
impl<T: PyPayload> PartialEq for PyInterned<T> {
176170
#[inline(always)]
177171
fn eq(&self, other: &Self) -> bool {
178172
std::ptr::eq(self, other)
179173
}
180174
}
181175

182-
impl Eq for PyStrInterned {}
176+
impl<T: PyPayload> Eq for PyInterned<T> {}
183177

184-
impl AsRef<str> for PyStrInterned {
185-
#[inline(always)]
186-
fn as_ref(&self) -> &str {
187-
self.as_str()
178+
impl<T: PyPayload + std::fmt::Debug> std::fmt::Debug for PyInterned<T> {
179+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
180+
std::fmt::Debug::fmt(&**self, f)?;
181+
write!(f, "@{:p}", self.as_ptr())
188182
}
189183
}
190184

191-
impl std::fmt::Debug for PyStrInterned {
192-
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
193-
std::fmt::Debug::fmt(self.as_str(), f)?;
194-
write!(f, "@{:p}", self.as_ptr())
185+
impl<T: PyPayload> ToPyObject for &'static PyInterned<T> {
186+
fn to_pyobject(self, _vm: &VirtualMachine) -> PyObjectRef {
187+
self.to_owned().into()
188+
}
189+
}
190+
191+
/// The unique reference of interned PyStr
192+
/// Always intended to be used as a static reference
193+
pub type PyStrInterned = PyInterned<PyStr>;
194+
195+
impl PyStrInterned {
196+
/// # Safety
197+
/// the given cache must be alive while returned reference is alive
198+
#[inline]
199+
unsafe fn borrow_cache(cache: &CachedPyStrRef) -> &'static Self {
200+
std::mem::transmute_copy(cache)
201+
}
202+
203+
#[inline]
204+
pub fn to_exact(&'static self) -> PyRefExact<PyStr> {
205+
unsafe { PyRefExact::new_unchecked(self.to_owned()) }
195206
}
196207
}
197208

@@ -201,6 +212,13 @@ impl std::fmt::Display for PyStrInterned {
201212
}
202213
}
203214

215+
impl AsRef<str> for PyStrInterned {
216+
#[inline(always)]
217+
fn as_ref(&self) -> &str {
218+
self.as_str()
219+
}
220+
}
221+
204222
mod sealed {
205223
use crate::{
206224
builtins::PyStr,

vm/src/stdlib/sys.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ mod sys {
132132
} else {
133133
"unknown"
134134
})
135-
.to_str()
135+
.to_owned()
136136
}
137137

138138
#[pyattr]
@@ -513,7 +513,7 @@ mod sys {
513513

514514
#[pyfunction]
515515
fn intern(s: PyRefExact<PyStr>, vm: &VirtualMachine) -> PyRefExact<PyStr> {
516-
vm.ctx.intern_str(s).to_owned()
516+
vm.ctx.intern_str(s).to_exact()
517517
}
518518

519519
#[pyattr]

vm/src/vm/context.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,15 +80,14 @@ impl Context {
8080

8181
let new_str = unsafe { string_pool.intern("__new__", types.str_type.clone()) };
8282
let slot_new_wrapper = create_object(
83-
PyNativeFuncDef::new(PyType::__new__.into_func(), new_str.to_owned().into_pyref())
84-
.into_function(),
83+
PyNativeFuncDef::new(PyType::__new__.into_func(), new_str.to_owned()).into_function(),
8584
&types.builtin_function_or_method_type,
8685
)
8786
.into();
8887

8988
let true_str = unsafe { string_pool.intern("True", types.str_type.clone()) };
9089
let false_str = unsafe { string_pool.intern("False", types.str_type.clone()) };
91-
let empty_str = unsafe { string_pool.intern("", types.str_type.clone()) }.to_str();
90+
let empty_str = unsafe { string_pool.intern("", types.str_type.clone()) }.to_owned();
9291

9392
let context = Context {
9493
true_value,

0 commit comments

Comments
 (0)