Merge pull request #3711 from youknowone/pyexact

PyExact as counterpart of PyRefExact
This commit is contained in:
Jeong YunWon
2022-05-18 10:22:10 +09:00
committed by GitHub
6 changed files with 138 additions and 27 deletions

View File

@@ -16,7 +16,7 @@ use crate::{
AsMapping, AsSequence, Comparable, Constructor, Hashable, IterNext, IterNextIterable,
Iterable, PyComparisonOp, Unconstructible,
},
AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyRefExact, PyResult,
AsObject, Context, Py, PyExact, PyObject, PyObjectRef, PyPayload, PyRef, PyRefExact, PyResult,
TryFromBorrowedObject, VirtualMachine,
};
use ascii::{AsciiStr, AsciiString};
@@ -1534,6 +1534,12 @@ impl AsRef<str> for PyRefExact<PyStr> {
}
}
impl AsRef<str> for PyExact<PyStr> {
fn as_ref(&self) -> &str {
self.as_str()
}
}
#[cfg(test)]
mod tests {
use super::*;

View File

@@ -10,7 +10,7 @@ use crate::common::{
use crate::{
builtins::{PyInt, PyStr, PyStrRef},
convert::ToPyObject,
AsObject, Py, PyObject, PyObjectRef, PyRefExact, PyResult, VirtualMachine,
AsObject, Py, PyExact, PyObject, PyObjectRef, PyRefExact, PyResult, VirtualMachine,
};
use num_traits::ToPrimitive;
use std::{fmt, mem::size_of, ops::ControlFlow};
@@ -686,23 +686,23 @@ pub trait DictKey {
/// to index dictionaries.
impl DictKey for PyObject {
type Owned = PyObjectRef;
#[inline]
#[inline(always)]
fn _to_owned(&self, _vm: &VirtualMachine) -> Self::Owned {
self.to_owned()
}
#[inline(always)]
fn key_hash(&self, vm: &VirtualMachine) -> PyResult<HashValue> {
self.hash(vm)
}
#[inline(always)]
fn key_is(&self, other: &PyObject) -> bool {
self.is(other)
}
#[inline(always)]
fn key_eq(&self, vm: &VirtualMachine, other_key: &PyObject) -> PyResult<bool> {
vm.identical_or_equal(self, other_key)
}
#[inline]
fn key_as_isize(&self, vm: &VirtualMachine) -> PyResult<isize> {
vm.to_index(self)?.try_to_primitive(vm)
}
@@ -710,15 +710,15 @@ impl DictKey for PyObject {
impl DictKey for Py<PyStr> {
type Owned = PyStrRef;
#[inline]
#[inline(always)]
fn _to_owned(&self, _vm: &VirtualMachine) -> Self::Owned {
self.to_owned()
}
#[inline]
fn key_hash(&self, vm: &VirtualMachine) -> PyResult<HashValue> {
Ok(self.hash(vm))
}
#[inline(always)]
fn key_is(&self, other: &PyObject) -> bool {
self.is(other)
}
@@ -732,28 +732,31 @@ impl DictKey for Py<PyStr> {
vm.bool_eq(self.as_object(), other_key)
}
}
#[inline(always)]
fn key_as_isize(&self, vm: &VirtualMachine) -> PyResult<isize> {
self.as_object().key_as_isize(vm)
}
}
impl DictKey for PyRefExact<PyStr> {
type Owned = Self;
#[inline]
impl DictKey for PyExact<PyStr> {
type Owned = PyRefExact<PyStr>;
#[inline(always)]
fn _to_owned(&self, _vm: &VirtualMachine) -> Self::Owned {
self.clone()
self.to_owned()
}
#[inline(always)]
fn key_hash(&self, vm: &VirtualMachine) -> PyResult<HashValue> {
(**self).key_hash(vm)
}
#[inline]
fn key_is(&self, other: &PyObject) -> bool {
(**self).key_is(other)
}
#[inline(always)]
fn key_eq(&self, vm: &VirtualMachine, other_key: &PyObject) -> PyResult<bool> {
(**self).key_eq(vm, other_key)
}
#[inline(always)]
fn key_as_isize(&self, vm: &VirtualMachine) -> PyResult<isize> {
(**self).key_as_isize(vm)
}
@@ -765,16 +768,16 @@ impl DictKey for PyRefExact<PyStr> {
/// to index dictionaries.
impl DictKey for str {
type Owned = String;
#[inline]
#[inline(always)]
fn _to_owned(&self, _vm: &VirtualMachine) -> Self::Owned {
self.to_owned()
}
#[inline]
fn key_hash(&self, vm: &VirtualMachine) -> PyResult<HashValue> {
// follow a similar route as the hashing of PyStrRef
Ok(vm.state.hash_secret.hash_str(self))
}
#[inline(always)]
fn key_is(&self, _other: &PyObject) -> bool {
// No matter who the other pyobject is, we are never the same thing, since
// we are a str, not a pyobject.

View File

@@ -2,7 +2,7 @@ use crate::{
builtins::{PyStr, PyTypeRef},
common::lock::PyRwLock,
convert::ToPyObject,
Py, PyObject, PyObjectRef, PyRef, PyRefExact,
Py, PyExact, PyObject, PyObjectRef, PyRef, PyRefExact,
};
use std::{
borrow::{Borrow, ToOwned},
@@ -199,7 +199,7 @@ impl std::fmt::Display for PyStrInterned {
mod sealed {
use crate::{
builtins::PyStr,
object::{Py, PyRefExact},
object::{Py, PyExact, PyRefExact},
};
pub trait SealedInternable {}
@@ -211,7 +211,7 @@ mod sealed {
pub trait SealedMaybeInterned {}
impl SealedMaybeInterned for str {}
impl SealedMaybeInterned for PyRefExact<PyStr> {}
impl SealedMaybeInterned for PyExact<PyStr> {}
impl SealedMaybeInterned for Py<PyStr> {}
}
@@ -259,6 +259,13 @@ impl MaybeInterned for str {
}
}
impl MaybeInterned for PyExact<PyStr> {
#[inline(always)]
fn as_interned(&self) -> Option<&'static PyStrInterned> {
None
}
}
impl MaybeInterned for Py<PyStr> {
#[inline(always)]
fn as_interned(&self) -> Option<&'static PyStrInterned> {

View File

@@ -77,7 +77,7 @@ pub mod vm;
pub use self::convert::{TryFromBorrowedObject, TryFromObject};
pub use self::object::{
AsObject, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyRefExact, PyResult, PyWeakRef,
AsObject, Py, PyExact, PyObject, PyObjectRef, PyPayload, PyRef, PyRefExact, PyResult, PyWeakRef,
};
pub use self::vm::{Context, Interpreter, Settings, VirtualMachine};

View File

@@ -58,7 +58,66 @@ where
}
}
#[repr(transparent)]
pub struct PyExact<T: PyObjectPayload> {
inner: Py<T>,
}
impl<T: PyPayload> PyExact<T> {
/// # Safety
/// Given reference must be exact type of payload T
#[inline(always)]
pub unsafe fn ref_unchecked(r: &Py<T>) -> &Self {
&*(r as *const _ as *const Self)
}
}
impl<T: PyPayload> Deref for PyExact<T> {
type Target = Py<T>;
#[inline(always)]
fn deref(&self) -> &Py<T> {
&self.inner
}
}
impl<T: PyObjectPayload> Borrow<PyObject> for PyExact<T> {
#[inline(always)]
fn borrow(&self) -> &PyObject {
self.inner.borrow()
}
}
impl<T: PyObjectPayload> AsRef<PyObject> for PyExact<T> {
#[inline(always)]
fn as_ref(&self) -> &PyObject {
self.inner.as_ref()
}
}
impl<T: PyObjectPayload> Borrow<Py<T>> for PyExact<T> {
#[inline(always)]
fn borrow(&self) -> &Py<T> {
&self.inner
}
}
impl<T: PyObjectPayload> AsRef<Py<T>> for PyExact<T> {
#[inline(always)]
fn as_ref(&self) -> &Py<T> {
&self.inner
}
}
impl<T: PyPayload> std::borrow::ToOwned for PyExact<T> {
type Owned = PyRefExact<T>;
fn to_owned(&self) -> Self::Owned {
let owned = self.inner.to_owned();
unsafe { PyRefExact::new_unchecked(owned) }
}
}
#[derive(Debug)]
#[repr(transparent)]
pub struct PyRefExact<T: PyObjectPayload> {
inner: PyRef<T>,
}
@@ -109,10 +168,31 @@ impl<T: PyPayload> TryFromObject for PyRefExact<T> {
}
impl<T: PyPayload> Deref for PyRefExact<T> {
type Target = PyRef<T>;
type Target = PyExact<T>;
#[inline(always)]
fn deref(&self) -> &PyRef<T> {
&self.inner
fn deref(&self) -> &PyExact<T> {
unsafe { PyExact::ref_unchecked(self.inner.deref()) }
}
}
impl<T: PyObjectPayload> Borrow<PyObject> for PyRefExact<T> {
#[inline(always)]
fn borrow(&self) -> &PyObject {
self.inner.borrow()
}
}
impl<T: PyObjectPayload> AsRef<PyObject> for PyRefExact<T> {
#[inline(always)]
fn as_ref(&self) -> &PyObject {
self.inner.as_ref()
}
}
impl<T: PyObjectPayload> Borrow<Py<T>> for PyRefExact<T> {
#[inline(always)]
fn borrow(&self) -> &Py<T> {
self.inner.borrow()
}
}
@@ -123,6 +203,20 @@ impl<T: PyObjectPayload> AsRef<Py<T>> for PyRefExact<T> {
}
}
impl<T: PyPayload> Borrow<PyExact<T>> for PyRefExact<T> {
#[inline(always)]
fn borrow(&self) -> &PyExact<T> {
self
}
}
impl<T: PyPayload> AsRef<PyExact<T>> for PyRefExact<T> {
#[inline(always)]
fn as_ref(&self) -> &PyExact<T> {
self
}
}
impl<T: PyPayload> ToPyObject for PyRefExact<T> {
#[inline(always)]
fn to_pyobject(self, _vm: &VirtualMachine) -> PyObjectRef {

View File

@@ -1,6 +1,7 @@
pub use crate::{
object::{
AsObject, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyRefExact, PyResult, PyWeakRef,
AsObject, Py, PyExact, PyObject, PyObjectRef, PyPayload, PyRef, PyRefExact, PyResult,
PyWeakRef,
},
vm::{Context, Interpreter, Settings, VirtualMachine},
};