diff --git a/vm/src/builtins/mod.rs b/vm/src/builtins/mod.rs index b3fd1a317..1b3cbb7a0 100644 --- a/vm/src/builtins/mod.rs +++ b/vm/src/builtins/mod.rs @@ -59,7 +59,7 @@ pub(crate) mod bool_; pub use bool_::PyBool; #[path = "str.rs"] pub(crate) mod pystr; -pub use pystr::{PyStr, PyStrRef}; +pub use pystr::{PyStr, PyStrInterned, PyStrRef}; #[path = "super.rs"] pub(crate) mod super_; pub use super_::PySuper; diff --git a/vm/src/builtins/str.rs b/vm/src/builtins/str.rs index 151a1f1d3..0137337c1 100644 --- a/vm/src/builtins/str.rs +++ b/vm/src/builtins/str.rs @@ -9,6 +9,7 @@ use crate::{ convert::{ToPyException, ToPyObject}, format::{FormatSpec, FormatString, FromTemplate}, function::{ArgIterable, FuncArgs, OptionalArg, OptionalOption, PyComparisonValue}, + intern::PyInterned, protocol::{PyIterReturn, PyMappingMethods, PySequenceMethods}, sequence::SequenceOp, sliceable::{SequenceIndex, SliceableSequenceOp}, @@ -227,7 +228,7 @@ impl IntoPyStrRef for &str { } } -impl IntoPyStrRef for &'static crate::intern::PyStrInterned { +impl IntoPyStrRef for &'static PyStrInterned { #[inline] fn into_pystr_ref(self, _vm: &VirtualMachine) -> PyRef { self.to_owned() @@ -1741,3 +1742,27 @@ impl<'s> AnyStr<'s> for str { splited } } + +/// The unique reference of interned PyStr +/// Always intended to be used as a static reference +pub type PyStrInterned = PyInterned; + +impl PyStrInterned { + #[inline] + pub fn to_exact(&'static self) -> PyRefExact { + unsafe { PyRefExact::new_unchecked(self.to_owned()) } + } +} + +impl std::fmt::Display for PyStrInterned { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.as_str(), f) + } +} + +impl AsRef for PyStrInterned { + #[inline(always)] + fn as_ref(&self) -> &str { + self.as_str() + } +} diff --git a/vm/src/intern.rs b/vm/src/intern.rs index 817871a19..ddef87c8e 100644 --- a/vm/src/intern.rs +++ b/vm/src/intern.rs @@ -1,5 +1,5 @@ use crate::{ - builtins::{PyStr, PyTypeRef}, + builtins::{PyStr, PyStrInterned, PyTypeRef}, common::lock::PyRwLock, convert::ToPyObject, AsObject, Py, PyExact, PyObject, PyObjectRef, PyPayload, PyRef, PyRefExact, VirtualMachine, @@ -42,17 +42,16 @@ impl StringPool { let cache = CachedPyStrRef { inner: s }; let inserted = zelf.inner.write().insert(cache.clone()); if inserted { - let interned = unsafe { PyStrInterned::borrow_cache(&cache) }; + let interned = unsafe { cache.as_interned_str() }; unsafe { interned.as_object().mark_intern() }; interned } else { unsafe { - PyStrInterned::borrow_cache( - zelf.inner - .read() - .get(cache.as_ref()) - .expect("inserted is false"), - ) + zelf.inner + .read() + .get(cache.as_ref()) + .expect("inserted is false") + .as_interned_str() } } } @@ -68,7 +67,7 @@ impl StringPool { self.inner .read() .get(s.as_ref()) - .map(|cached| unsafe { PyStrInterned::borrow_cache(cached) }) + .map(|cached| unsafe { cached.as_interned_str() }) } } @@ -107,6 +106,13 @@ impl AsRef for CachedPyStrRef { } impl CachedPyStrRef { + /// # Safety + /// the given cache must be alive while returned reference is alive + #[inline] + unsafe fn as_interned_str(&self) -> &'static PyStrInterned { + std::mem::transmute_copy(self) + } + #[inline] fn as_str(&self) -> &str { self.inner.as_str() @@ -188,37 +194,6 @@ impl ToPyObject for &'static PyInterned { } } -/// The unique reference of interned PyStr -/// Always intended to be used as a static reference -pub type PyStrInterned = PyInterned; - -impl PyStrInterned { - /// # Safety - /// the given cache must be alive while returned reference is alive - #[inline] - unsafe fn borrow_cache(cache: &CachedPyStrRef) -> &'static Self { - std::mem::transmute_copy(cache) - } - - #[inline] - pub fn to_exact(&'static self) -> PyRefExact { - unsafe { PyRefExact::new_unchecked(self.to_owned()) } - } -} - -impl std::fmt::Display for PyStrInterned { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - std::fmt::Display::fmt(self.as_str(), f) - } -} - -impl AsRef for PyStrInterned { - #[inline(always)] - fn as_ref(&self) -> &str { - self.as_str() - } -} - mod sealed { use crate::{ builtins::PyStr, diff --git a/vm/src/stdlib/sys.rs b/vm/src/stdlib/sys.rs index d21229dfe..b342d1a85 100644 --- a/vm/src/stdlib/sys.rs +++ b/vm/src/stdlib/sys.rs @@ -512,8 +512,8 @@ mod sys { } #[pyfunction] - fn intern(s: PyRefExact, vm: &VirtualMachine) -> PyRefExact { - vm.ctx.intern_str(s).to_exact() + fn intern(s: PyRefExact, vm: &VirtualMachine) -> PyRef { + vm.ctx.intern_str(s).to_owned() } #[pyattr] diff --git a/vm/src/vm/context.rs b/vm/src/vm/context.rs index c4ec499a4..708d621c3 100644 --- a/vm/src/vm/context.rs +++ b/vm/src/vm/context.rs @@ -7,13 +7,13 @@ use crate::{ object, pystr, type_::PyAttributes, PyBaseException, PyComplex, PyDict, PyDictRef, PyEllipsis, PyFloat, PyFrozenSet, PyInt, - PyIntRef, PyList, PyListRef, PyNone, PyNotImplemented, PyStr, PyTuple, PyTupleRef, PyType, - PyTypeRef, + PyIntRef, PyList, PyListRef, PyNone, PyNotImplemented, PyStr, PyStrInterned, PyTuple, + PyTupleRef, PyType, PyTypeRef, }, class::{PyClassImpl, StaticType}, exceptions, function::IntoPyNativeFunc, - intern::{Internable, MaybeInterned, PyStrInterned, StringPool}, + intern::{Internable, MaybeInterned, StringPool}, object::{PyObjectPayload, PyObjectRef, PyPayload, PyRef}, types::{PyTypeFlags, PyTypeSlots, TypeZoo}, };