Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion Lib/test/test_descr.py
Original file line number Diff line number Diff line change
Expand Up @@ -1788,7 +1788,6 @@ class D(C):
self.assertEqual(b.foo, 3)
self.assertEqual(b.__class__, D)

@unittest.expectedFailure
def test_bad_new(self):
self.assertRaises(TypeError, object.__new__)
self.assertRaises(TypeError, object.__new__, '')
Expand Down
18 changes: 7 additions & 11 deletions crates/derive-impl/src/pyclass.rs
Original file line number Diff line number Diff line change
Expand Up @@ -954,7 +954,10 @@ where
} else if let Ok(f) = args.item.function_or_method() {
(&f.sig().ident, f.span())
} else {
return Err(self.new_syn_error(args.item.span(), "can only be on a method"));
return Err(self.new_syn_error(
args.item.span(),
"can only be on a method or const function pointer",
));
};

let item_attr = args.attrs.remove(self.index());
Expand Down Expand Up @@ -1496,7 +1499,9 @@ impl SlotItemMeta {
}
} else {
let ident_str = self.inner().item_name();
let name = if let Some(stripped) = ident_str.strip_prefix("slot_") {
// Convert to lowercase to handle both SLOT_NEW and slot_new
let ident_lower = ident_str.to_lowercase();
let name = if let Some(stripped) = ident_lower.strip_prefix("slot_") {
proc_macro2::Ident::new(stripped, inner.item_ident.span())
} else {
inner.item_ident.clone()
Expand Down Expand Up @@ -1609,7 +1614,6 @@ fn extract_impl_attrs(attr: PunctuatedNestedMeta, item: &Ident) -> Result<Extrac
}];
let mut payload = None;

let mut has_constructor = false;
for attr in attr {
match attr {
NestedMeta::Meta(Meta::List(MetaList { path, nested, .. })) => {
Expand All @@ -1634,9 +1638,6 @@ fn extract_impl_attrs(attr: PunctuatedNestedMeta, item: &Ident) -> Result<Extrac
"Try `#[pyclass(with(Constructor, ...))]` instead of `#[pyclass(with(DefaultConstructor, ...))]`. DefaultConstructor implicitly implements Constructor."
)
}
if path.is_ident("Constructor") || path.is_ident("Unconstructible") {
has_constructor = true;
}
(
quote!(<Self as #path>::__extend_py_class),
quote!(<Self as #path>::__OWN_METHOD_DEFS),
Expand Down Expand Up @@ -1689,11 +1690,6 @@ fn extract_impl_attrs(attr: PunctuatedNestedMeta, item: &Ident) -> Result<Extrac
attr => bail_span!(attr, "Unknown pyimpl attribute"),
}
}
// TODO: DISALLOW_INSTANTIATION check is required
let _ = has_constructor;
// if !withs.is_empty() && !has_constructor {
// bail_span!(item, "#[pyclass(with(...))] does not have a Constructor. Either #[pyclass(with(Constructor, ...))] or #[pyclass(with(Unconstructible, ...))] is mandatory. Consider to add `impl DefaultConstructor for T {{}}` or `impl Unconstructible for T {{}}`.")
// }

Ok(ExtractedImplAttrs {
payload,
Expand Down
2 changes: 1 addition & 1 deletion crates/stdlib/src/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1399,7 +1399,7 @@ mod array {
internal: PyMutex<PositionIterInternal<PyArrayRef>>,
}

#[pyclass(with(IterNext, Iterable), flags(HAS_DICT))]
#[pyclass(with(IterNext, Iterable), flags(HAS_DICT, DISALLOW_INSTANTIATION))]
impl PyArrayIter {
#[pymethod]
fn __setstate__(&self, state: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
Expand Down
4 changes: 2 additions & 2 deletions crates/stdlib/src/csv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -908,7 +908,7 @@ mod _csv {
}
}

#[pyclass(with(IterNext, Iterable))]
#[pyclass(with(IterNext, Iterable), flags(DISALLOW_INSTANTIATION))]
impl Reader {
#[pygetset]
fn line_num(&self) -> u64 {
Expand Down Expand Up @@ -1059,7 +1059,7 @@ mod _csv {
}
}

#[pyclass]
#[pyclass(flags(DISALLOW_INSTANTIATION))]
impl Writer {
#[pygetset(name = "dialect")]
const fn get_dialect(&self, _vm: &VirtualMachine) -> PyDialect {
Expand Down
6 changes: 3 additions & 3 deletions crates/stdlib/src/pystruct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ pub(crate) mod _struct {
function::{ArgBytesLike, ArgMemoryBuffer, PosArgs},
match_class,
protocol::PyIterReturn,
types::{Constructor, IterNext, Iterable, Representable, SelfIter, Unconstructible},
types::{Constructor, IterNext, Iterable, Representable, SelfIter},
};
use crossbeam_utils::atomic::AtomicCell;

Expand Down Expand Up @@ -189,15 +189,15 @@ pub(crate) mod _struct {
}
}

#[pyclass(with(Unconstructible, IterNext, Iterable))]
#[pyclass(with(IterNext, Iterable), flags(DISALLOW_INSTANTIATION))]
impl UnpackIterator {
#[pymethod]
fn __length_hint__(&self) -> usize {
self.buffer.len().saturating_sub(self.offset.load()) / self.format_spec.size
}
}
impl SelfIter for UnpackIterator {}
impl Unconstructible for UnpackIterator {}

impl IterNext for UnpackIterator {
fn next(zelf: &Py<Self>, vm: &VirtualMachine) -> PyResult<PyIterReturn> {
let size = zelf.format_spec.size;
Expand Down
10 changes: 3 additions & 7 deletions crates/stdlib/src/sqlite.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ mod _sqlite {
sliceable::{SaturatedSliceIter, SliceableSequenceOp},
types::{
AsMapping, AsNumber, AsSequence, Callable, Comparable, Constructor, Hashable,
Initializer, IterNext, Iterable, PyComparisonOp, SelfIter, Unconstructible,
Initializer, IterNext, Iterable, PyComparisonOp, SelfIter,
},
utils::ToCString,
};
Expand Down Expand Up @@ -2197,8 +2197,6 @@ mod _sqlite {
inner: PyMutex<Option<BlobInner>>,
}

impl Unconstructible for Blob {}

#[derive(Debug)]
struct BlobInner {
blob: SqliteBlob,
Expand All @@ -2211,7 +2209,7 @@ mod _sqlite {
}
}

#[pyclass(with(AsMapping, Unconstructible, AsNumber, AsSequence))]
#[pyclass(flags(DISALLOW_INSTANTIATION), with(AsMapping, AsNumber, AsSequence))]
impl Blob {
#[pymethod]
fn close(&self) {
Expand Down Expand Up @@ -2592,9 +2590,7 @@ mod _sqlite {
}
}

impl Unconstructible for Statement {}

#[pyclass(with(Unconstructible))]
#[pyclass(flags(DISALLOW_INSTANTIATION))]
impl Statement {
fn new(
connection: &Connection,
Expand Down
2 changes: 1 addition & 1 deletion crates/stdlib/src/unicodedata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ mod unicodedata {
}
}

#[pyclass]
#[pyclass(flags(DISALLOW_INSTANTIATION))]
impl Ucd {
#[pymethod]
fn category(&self, character: PyStrRef, vm: &VirtualMachine) -> PyResult<String> {
Expand Down
4 changes: 2 additions & 2 deletions crates/stdlib/src/zlib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ mod zlib {
inner: PyMutex<PyDecompressInner>,
}

#[pyclass]
#[pyclass(flags(DISALLOW_INSTANTIATION))]
impl PyDecompress {
#[pygetset]
fn eof(&self) -> bool {
Expand Down Expand Up @@ -383,7 +383,7 @@ mod zlib {
inner: PyMutex<CompressState<CompressInner>>,
}

#[pyclass]
#[pyclass(flags(DISALLOW_INSTANTIATION))]
impl PyCompress {
#[pymethod]
fn compress(&self, data: ArgBytesLike, vm: &VirtualMachine) -> PyResult<Vec<u8>> {
Expand Down
6 changes: 2 additions & 4 deletions crates/vm/src/builtins/asyncgenerator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::{
frame::FrameRef,
function::OptionalArg,
protocol::PyIterReturn,
types::{IterNext, Iterable, Representable, SelfIter, Unconstructible},
types::{IterNext, Iterable, Representable, SelfIter},
};

use crossbeam_utils::atomic::AtomicCell;
Expand All @@ -32,7 +32,7 @@ impl PyPayload for PyAsyncGen {
}
}

#[pyclass(with(PyRef, Unconstructible, Representable))]
#[pyclass(flags(DISALLOW_INSTANTIATION), with(PyRef, Representable))]
impl PyAsyncGen {
pub const fn as_coro(&self) -> &Coro {
&self.inner
Expand Down Expand Up @@ -201,8 +201,6 @@ impl Representable for PyAsyncGen {
}
}

impl Unconstructible for PyAsyncGen {}

#[pyclass(module = false, name = "async_generator_wrapped_value")]
#[derive(Debug)]
pub(crate) struct PyAsyncGenWrappedValue(pub PyObjectRef);
Expand Down
12 changes: 4 additions & 8 deletions crates/vm/src/builtins/builtin_func.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::{
common::wtf8::Wtf8,
convert::TryFromObject,
function::{FuncArgs, PyComparisonValue, PyMethodDef, PyMethodFlags, PyNativeFn},
types::{Callable, Comparable, PyComparisonOp, Representable, Unconstructible},
types::{Callable, Comparable, PyComparisonOp, Representable},
};
use std::fmt;

Expand Down Expand Up @@ -74,7 +74,7 @@ impl Callable for PyNativeFunction {
}
}

#[pyclass(with(Callable, Unconstructible), flags(HAS_DICT))]
#[pyclass(with(Callable), flags(HAS_DICT, DISALLOW_INSTANTIATION))]
impl PyNativeFunction {
#[pygetset]
fn __module__(zelf: NativeFunctionOrMethod) -> Option<&'static PyStrInterned> {
Expand Down Expand Up @@ -145,8 +145,6 @@ impl Representable for PyNativeFunction {
}
}

impl Unconstructible for PyNativeFunction {}

// `PyCMethodObject` in CPython
#[pyclass(name = "builtin_method", module = false, base = PyNativeFunction, ctx = "builtin_method_type")]
pub struct PyNativeMethod {
Expand All @@ -155,8 +153,8 @@ pub struct PyNativeMethod {
}

#[pyclass(
with(Unconstructible, Callable, Comparable, Representable),
flags(HAS_DICT)
with(Callable, Comparable, Representable),
flags(HAS_DICT, DISALLOW_INSTANTIATION)
)]
impl PyNativeMethod {
#[pygetset]
Expand Down Expand Up @@ -246,8 +244,6 @@ impl Representable for PyNativeMethod {
}
}

impl Unconstructible for PyNativeMethod {}

pub fn init(context: &Context) {
PyNativeFunction::extend_class(context, context.types.builtin_function_or_method_type);
PyNativeMethod::extend_class(context, context.types.builtin_method_type);
Expand Down
6 changes: 2 additions & 4 deletions crates/vm/src/builtins/bytearray.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ use crate::{
types::{
AsBuffer, AsMapping, AsNumber, AsSequence, Callable, Comparable, Constructor,
DefaultConstructor, Initializer, IterNext, Iterable, PyComparisonOp, Representable,
SelfIter, Unconstructible,
SelfIter,
},
};
use bstr::ByteSlice;
Expand Down Expand Up @@ -865,7 +865,7 @@ impl PyPayload for PyByteArrayIterator {
}
}

#[pyclass(with(Unconstructible, IterNext, Iterable))]
#[pyclass(flags(DISALLOW_INSTANTIATION), with(IterNext, Iterable))]
impl PyByteArrayIterator {
#[pymethod]
fn __length_hint__(&self) -> usize {
Expand All @@ -886,8 +886,6 @@ impl PyByteArrayIterator {
}
}

impl Unconstructible for PyByteArrayIterator {}

impl SelfIter for PyByteArrayIterator {}
impl IterNext for PyByteArrayIterator {
fn next(zelf: &Py<Self>, vm: &VirtualMachine) -> PyResult<PyIterReturn> {
Expand Down
5 changes: 2 additions & 3 deletions crates/vm/src/builtins/bytes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use crate::{
sliceable::{SequenceIndex, SliceableSequenceOp},
types::{
AsBuffer, AsMapping, AsNumber, AsSequence, Callable, Comparable, Constructor, Hashable,
IterNext, Iterable, PyComparisonOp, Representable, SelfIter, Unconstructible,
IterNext, Iterable, PyComparisonOp, Representable, SelfIter,
},
};
use bstr::ByteSlice;
Expand Down Expand Up @@ -749,7 +749,7 @@ impl PyPayload for PyBytesIterator {
}
}

#[pyclass(with(Unconstructible, IterNext, Iterable))]
#[pyclass(flags(DISALLOW_INSTANTIATION), with(IterNext, Iterable))]
impl PyBytesIterator {
#[pymethod]
fn __length_hint__(&self) -> usize {
Expand All @@ -770,7 +770,6 @@ impl PyBytesIterator {
.set_state(state, |obj, pos| pos.min(obj.len()), vm)
}
}
impl Unconstructible for PyBytesIterator {}

impl SelfIter for PyBytesIterator {}
impl IterNext for PyBytesIterator {
Expand Down
6 changes: 2 additions & 4 deletions crates/vm/src/builtins/coroutine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::{
frame::FrameRef,
function::OptionalArg,
protocol::PyIterReturn,
types::{IterNext, Iterable, Representable, SelfIter, Unconstructible},
types::{IterNext, Iterable, Representable, SelfIter},
};
use crossbeam_utils::atomic::AtomicCell;

Expand All @@ -24,7 +24,7 @@ impl PyPayload for PyCoroutine {
}
}

#[pyclass(with(Py, Unconstructible, IterNext, Representable))]
#[pyclass(flags(DISALLOW_INSTANTIATION), with(Py, IterNext, Representable))]
impl PyCoroutine {
pub const fn as_coro(&self) -> &Coro {
&self.inner
Expand Down Expand Up @@ -123,8 +123,6 @@ impl Py<PyCoroutine> {
}
}

impl Unconstructible for PyCoroutine {}

impl Representable for PyCoroutine {
#[inline]
fn repr_str(zelf: &Py<Self>, vm: &VirtualMachine) -> PyResult<String> {
Expand Down
15 changes: 7 additions & 8 deletions crates/vm/src/builtins/descriptor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::{
builtins::{PyTypeRef, builtin_func::PyNativeMethod, type_},
class::PyClassImpl,
function::{FuncArgs, PyMethodDef, PyMethodFlags, PySetterValue},
types::{Callable, GetDescriptor, Representable, Unconstructible},
types::{Callable, GetDescriptor, Representable},
};
use rustpython_common::lock::PyRwLock;

Expand Down Expand Up @@ -105,8 +105,8 @@ impl PyMethodDescriptor {
}

#[pyclass(
with(GetDescriptor, Callable, Unconstructible, Representable),
flags(METHOD_DESCRIPTOR)
with(GetDescriptor, Callable, Representable),
flags(METHOD_DESCRIPTOR, DISALLOW_INSTANTIATION)
)]
impl PyMethodDescriptor {
#[pygetset]
Expand Down Expand Up @@ -159,8 +159,6 @@ impl Representable for PyMethodDescriptor {
}
}

impl Unconstructible for PyMethodDescriptor {}

#[derive(Debug)]
pub enum MemberKind {
Bool = 14,
Expand Down Expand Up @@ -246,7 +244,10 @@ fn calculate_qualname(descr: &PyDescriptorOwned, vm: &VirtualMachine) -> PyResul
}
}

#[pyclass(with(GetDescriptor, Unconstructible, Representable), flags(BASETYPE))]
#[pyclass(
with(GetDescriptor, Representable),
flags(BASETYPE, DISALLOW_INSTANTIATION)
)]
impl PyMemberDescriptor {
#[pygetset]
fn __doc__(&self) -> Option<String> {
Expand Down Expand Up @@ -339,8 +340,6 @@ fn set_slot_at_object(
Ok(())
}

impl Unconstructible for PyMemberDescriptor {}

impl Representable for PyMemberDescriptor {
#[inline]
fn repr_str(zelf: &Py<Self>, _vm: &VirtualMachine) -> PyResult<String> {
Expand Down
Loading
Loading