8000 Fix __parameters__, __type_params__ · RustPython/RustPython@f5d036e · GitHub
[go: up one dir, main page]

Skip to content

Commit f5d036e

Browse files
committed
Fix __parameters__, __type_params__
1 parent 481e03a commit f5d036e

File tree

8 files changed

+281
-83
lines changed

8 files changed

+281
-83
lines changed

Lib/test/test_module/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,7 @@ def test_annotations_getset_raises(self):
334334
del foo.__annotations__
335335

336336
def test_annotations_are_created_correctly(self):
337-
ann_module4 = import_helper.import_fresh_module('test.ann_module4')
337+
ann_module4 = import_helper.import_fresh_module('test.typinganndata.ann_module4')
338338
self.assertTrue("__annotations__" in ann_module4.__dict__)
339339
del ann_module4.__annotations__
340340
self.assertFalse("__annotations__" in ann_module4.__dict__)

Lib/test/test_typing.py

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -629,8 +629,6 @@ def test_typevar(self):
629629
class A(Generic[T]): ...
630630
Alias = Optional[T]
631631

632-
# TODO: RUSTPYTHON
633-
@unittest.expectedFailure
634632
def test_typevar_none(self):
635633
U = TypeVar('U')
636634
U_None = TypeVar('U_None', default=None)
@@ -1210,8 +1208,6 @@ def foo(**kwargs: Unpack[Movie]): ...
12101208
self.assertEqual(repr(foo.__annotations__['kwargs']),
12111209
f"typing.Unpack[{__name__}.Movie]")
12121210

1213-
# TODO: RUSTPYTHON
1214-
@unittest.expectedFailure
12151211
def test_builtin_tuple(self):
12161212
Ts = TypeVarTuple("Ts")
12171213

@@ -2636,11 +2632,6 @@ def test_consistency(self):
26362632
class CollectionsCallableTests(BaseCallableTests, BaseTestCase):
26372633
Callable = collections.abc.Callable
26382634

2639-
# TODO: RUSTPYTHON
2640-
@unittest.expectedFailure
2641-
def test_errors(self):
2642-
super().test_errors()
2643-
26442635

26452636
class LiteralTests(BaseTestCase):
26462637
def test_basics(self):
@@ -3608,8 +3599,6 @@ class C(B[int]):
36083599
c.bar = 'abc'
36093600
self.assertEqual(c.__dict__, {'bar': 'abc'})
36103601

3611-
# TODO: RUSTPYTHON
3612-
@unittest.expectedFailure
36133602
def test_setattr_exceptions(self):
36143603
class Immutable[T]:
36153604
def __setattr__(self, key, value):
@@ -3753,8 +3742,6 @@ class Meta(type): ...
37533742
self.assertEqual(Union[T, int][Meta], Union[Meta, int])
37543743
self.assertEqual(Callable[..., Meta].__args__, (Ellipsis, Meta))
37553744

3756-
# TODO: RUSTPYTHON
3757-
@unittest.expectedFailure
37583745
def test_generic_hashes(self):
37593746
class A(Generic[T]):
37603747
...
@@ -4302,8 +4289,6 @@ class B(Generic[T]):
43024289
self.assertEqual(A[T], A[T])
43034290
self.assertNotEqual(A[T], B[T])
43044291

4305-
# TODO: RUSTPYTHON
4306-
@unittest.expectedFailure
43074292
def test_multiple_inheritance(self):
43084293

43094294
class A(Generic[T, VT]):
@@ -7597,8 +7582,6 @@ class A[T](TypedDict):
75977582
self.assertEqual(A[str].__parameters__, ())
75987583
self.assertEqual(A[str].__args__, (str,))
75997584

7600-
# TODO: RUSTPYTHON
7601-
@unittest.expectedFailure
76027585
def test_generic_inheritance(self):
76037586
class A(TypedDict, Generic[T]):
76047587
a: T

compiler/codegen/src/compile.rs

Lines changed: 90 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1215,38 +1215,86 @@ impl Compiler<'_> {
12151215
// First, compile each type parameter and store it
12161216
for type_param in &type_params.type_params {
12171217
match type_param {
1218-
TypeParam::TypeVar(TypeParamTypeVar { name, bound, .. }) => {
1218+
TypeParam::TypeVar(TypeParamTypeVar {
1219+
name,
1220+
bound,
1221+
default,
1222+
..
1223+
}) => {
12191224
if let Some(expr) = &bound {
12201225
self.compile_expression(expr)?;
12211226
self.emit_load_const(ConstantData::Str {
12221227
value: name.as_str().into(),
12231228
});
12241229
emit!(self, Instruction::TypeVarWithBound);
1225-
emit!(self, Instruction::Duplicate);
1226-
self.store_name(name.as_ref())?;
12271230
} else {
1228-
// self.store_name(type_name.as_str())?;
12291231
self.emit_load_const(ConstantData::Str {
12301232
value: name.as_str().into(),
12311233
});
12321234
emit!(self, Instruction::TypeVar);
1233-
emit!(self, Instruction::Duplicate);
1234-
self.store_name(name.as_ref())?;
12351235
}
1236+
1237+
// Handle default value if present (PEP 695)
1238+
if let Some(default_expr) = default {
1239+
// Compile the default expression
1240+
self.compile_expression(default_expr)?;
1241+
1242+
emit!(
1243+
self,
1244+
Instruction::CallIntrinsic2 {
1245+
func: bytecode::IntrinsicFunction2::SetTypeparamDefault
1246+
}
1247+
);
1248+
}
1249+
1250+
emit!(self, Instruction::Duplicate);
1251+
self.store_name(name.as_ref())?;
12361252
}
1237-
TypeParam::ParamSpec(TypeParamParamSpec { name, .. }) => {
1253+
TypeParam::ParamSpec(TypeParamParamSpec { name, default, .. }) => {
12381254
self.emit_load_const(ConstantData::Str {
12391255
value: name.as_str().into(),
12401256
});
12411257
emit!(self, Instruction::ParamSpec);
1258+
1259+
// Handle default value if present (PEP 695)
1260+
if let Some(default_expr) = default {
1261+
// Compile the default expression
1262+
self.compile_expression(default_expr)?;
1263+
1264+
emit!(
1265+
self,
1266+
Instruction::CallIntrinsic2 {
1267+
func: bytecode::IntrinsicFunction2::SetTypeparamDefault
1268+
}
1269+
);
1270+
}
1271+
12421272
emit!(self, Instruction::Duplicate);
12431273
self.store_name(name.as_ref())?;
12441274
}
1245-
TypeParam::TypeVarTuple(TypeParamTypeVarTuple { name, .. }) => {
1275+
TypeParam::TypeVarTuple(TypeParamTypeVarTuple { name, default, .. }) => {
12461276
self.emit_load_const(ConstantData::Str {
12471277
value: name.as_str().into(),
12481278
});
12491279
emit!(self, Instruction::TypeVarTuple);
1280+
1281+
// Handle default value if present (PEP 695)
1282+
if let Some(default_expr) = default {
1283+
// Compile the default expression
1284+
self.compile_expression(default_expr)?;
1285+
1286+
// Handle starred expression (*default)
1287+
// CPython handles the unpacking during runtime evaluation of the default value
1288+
// We don't need special intrinsic for this - just compile the expression normally
1289+
1290+
emit!(
1291+
self,
1292+
Instruction::CallIntrinsic2 {
1293+
func: bytecode::IntrinsicFunction2::SetTypeparamDefault
1294+
}
1295+
);
1296+
}
1297+
12501298
emit!(self, Instruction::Duplicate);
12511299
self.store_name(name.as_ref())?;
12521300
}
@@ -1759,13 +1807,41 @@ impl Compiler<'_> {
17591807

17601808
self.emit_load_const(ConstantData::Str { value: name.into() });
17611809

1762-
// Call the __build_class__ builtin
1763-
let call = if let Some(arguments) = arguments {
1764-
self.compile_call_inner(2, arguments)?
1810+
// For PEP 695 classes: handle Generic base creation
1811+
if type_params.is_some() {
1812+
if let Some(arguments) = arguments {
1813+
// Has explicit bases - use them as is, don't add Generic
1814+
// CPython doesn't add Generic when explicit bases are present
1815+
let call = self.compile_call_inner(2, arguments)?;
1816+
self.compile_normal_call(call);
1817+
} else {
1818+
// No explicit bases, add Generic[*type_params] as the only base
1819+
// Stack currently: [function, class_name]
1820+
1821+
// Load .type_params for creating Generic base
1822+
let dot_type_params = self.name(".type_params");
1823+
emit!(self, Instruction::LoadNameAny(dot_type_params));
1824+
1825+
// Call INTRINSIC_SUBSCRIPT_GENERIC to create Generic[*type_params]
1826+
emit!(
1827+
self,
1828+
Instruction::CallIntrinsic1 {
1829+
func: bytecode::IntrinsicFunction1::SubscriptGeneric
1830+
}
1831+
);
1832+
1833+
// Call __build_class__ with 3 positional args: function, class_name, Generic[T]
1834+
emit!(self, Instruction::CallFunctionPositional { nargs: 3 });
1835+
}
17651836
} else {
1766-
CallType::Positional { nargs: 2 }
1767-
};
1768-
self.compile_normal_call(call);
1837+
// No type params, normal compilation
1838+
let call = if let Some(arguments) = arguments {
1839+
self.compile_call_inner(2, arguments)?
1840+
} else {
1841+
CallType::Positional { nargs: 2 }
1842+
};
1843+
self.compile_normal_call(call);
1844+
}
17691845

17701846
// Pop the special type params symbol table
17711847
if type_params.is_some() {

compiler/core/src/bytecode.rs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,49 @@ op_arg_enum!(
375375
}
376376
);
377377

378+
op_arg_enum!(
379+
/// Intrinsic function for CALL_INTRINSIC_1
380+
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
381+
#[repr(u8)]
382+
pub enum IntrinsicFunction1 {
383+
/// Import * special case
384+
// ImportStar = 0,
385+
/// Set stop iteration value
386+
// StopAsyncIteration = 1,
387+
/// Unary operators
388+
// UnaryPositive = 2,
389+
// UnaryNegative = 3,
390+
// UnaryNot = 4,
391+
// UnaryInvert = 5,
392+
/// Exit init subclass
393+
// ExitInitCheck = 6,
394+
/// Create a new list from an iterator
395+
// ListToTupleForCall = 7,
396+
/// Type parameter related
397+
// TypeVar = 8,
398+
// TypeVarTuple = 9,
399+
// ParamSpec = 10,
400+
/// Generic subscript for PEP 695
401+
SubscriptGeneric = 10,
402+
// TypeAlias = 12,
403+
// TypeParams = 13,
404+
}
405+
);
406+
407+
op_arg_enum!(
408+
/// Intrinsic function for CALL_INTRINSIC_2
409+
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
410+
#[repr(u8)]
411+
pub enum IntrinsicFunction2 {
412+
// PrepReraiseS tar = 1,
413+
// TypeVarWithBound = 2,
414+
// TypeVarWithConstraints = 3,
415+
// SetFunctionTypeParams = 4,
416+
/// Set default value for type parameter (PEP 695)
417+
SetTypeparamDefault = 5,
418+
}
419+
);
420+
378421
pub type NameIdx = u32;
379422

380423
/// A Single bytecode instruction.
@@ -454,6 +497,12 @@ pub enum Instruction {
454497
Duplicate2,
455498
GetIter,
456499
GetLen,
500+
CallIntrinsic1 {
501+
func: Arg<IntrinsicFunction1>,
502+
},
503+
CallIntrinsic2 {
504+
func: Arg<IntrinsicFunction2>,
505+
},
457506
Continue {
458507
target: Arg<Label>,
459508
},
@@ -1235,6 +1284,8 @@ impl Instruction {
12351284
Duplicate2 => 2,
12361285
GetIter => 0,
12371286
GetLen => 1,
1287+
CallIntrinsic1 { .. } => 0, // Takes 1, pushes 1
1288+
CallIntrinsic2 { .. } => -1, // Takes 2, pushes 1
12381289
Continue { .. } => 0,
12391290
Break { .. } => 0,
12401291
Jump { .. } => 0,
@@ -1444,6 +1495,8 @@ impl Instruction {
14441495
GetIter => w!(GetIter),
14451496
// GET_LEN
14461497
GetLen => w!(GetLen),
1498+
CallIntrinsic1 { func } => w!(CallIntrinsic1, ?func),
1499+
CallIntrinsic2 { func } => w!(CallIntrinsic2, ?func),
14471500
Continue { target } => w!(Continue, target),
14481501
Break { target } => w!(Break, target),
14491502
Jump { target } => w!(Jump, target),

vm/src/builtins/genericalias.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -613,6 +613,25 @@ impl Iterable for PyGenericAlias {
613613
}
614614
}
615615

616+
/// Creates a GenericAlias from type parameters, equivalent to CPython's _Py_subscript_generic
617+
/// This is used for PEP 695 classes to create Generic[T] from type parameters
618+
// _Py_subscript_generic
619+
pub fn subscript_generic(type_params: PyObjectRef, vm: &VirtualMachine) -> PyResult {
620+
// Get typing.Generic type
621+
let typing_module = vm.import("typing", 0)?;
622+
let generic_type = typing_module.get_attr("Generic", vm)?;
623+
let generic_type = PyTypeRef::try_from_object(vm, generic_type)?;
624+
625+
// Create GenericAlias: Generic[type_params]
626+
let args = if let Ok(tuple) = type_params.try_to_ref::<PyTuple>(vm) {
627+
tuple.to_owned()
628+
} else {
629+
PyTuple::new_ref(vec![type_params], &vm.ctx)
630+
};
631+
632+
Ok(PyGenericAlias::new(generic_type, args, false, vm).into_pyobject(vm))
633+
}
634+
616635
pub fn init(context: &Context) {
617636
let generic_alias_type = &context.types.generic_alias_type;
618637
PyGenericAlias::extend_class(context, generic_alias_type);

vm/src/frame.rs

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1050,6 +1050,19 @@ impl ExecutingFrame<'_> {
10501050
self.push_value(vm.ctx.new_int(len).into());
10511051
Ok(None)
10521052
}
1053+
bytecode::Instruction::CallIntrinsic1 { func } => {
1054+
let value = self.pop_value();
1055+
let result = self.call_intrinsic_1(func.get(arg), value, vm)?;
1056+
self.push_value(result);
1057+
Ok(None)
1058+
}
1059+
bytecode::Instruction::CallIntrinsic2 { func } => {
1060+
let value2 = self.pop_value();
1061+
let value1 = self.pop_value();
1062+
let result = self.call_intrinsic_2(func.get(arg), value1, value2, vm)?;
1063+
self.push_value(result);
1064+
Ok(None)
1065+
}
10531066
bytecode::Instruction::GetAwaitable => {
10541067
let awaited_obj = self.pop_value();
10551068
let awaitable = if awaited_obj.payload_is::<PyCoroutine>() {
@@ -1288,7 +1301,7 @@ impl ExecutingFrame<'_> {
12881301
}
12891302
bytecode::Instruction::ParamSpec => {
12901303
let param_spec_name = self.pop_value();
1291-
let param_spec: PyObjectRef = typing::ParamSpec::new(param_spec_name.clone())
1304+
let param_spec: PyObjectRef = typing::ParamSpec::new(param_spec_name.clone(), vm)
12921305
.into_ref(&vm.ctx)
12931306
.into();
12941307
self.push_value(param_spec);
@@ -2244,6 +2257,34 @@ impl ExecutingFrame<'_> {
22442257
}
22452258
}
22462259

2260+
fn call_intrinsic_1(
2261+
&mut self,
2262+
func: bytecode::IntrinsicFunction1,
2263+
arg: PyObjectRef,
2264+
vm: &VirtualMachine,
2265+
) -> PyResult {
2266+
match func {
2267+
bytecode::IntrinsicFunction1::SubscriptGeneric => {
2268+
// Used for PEP 695: Generic[*type_params]
2269+
crate::builtins::genericalias::subscript_generic(arg, vm)
2270+
}
2271+
}
2272+
}
2273+
2274+
fn call_intrinsic_2(
2275+
&mut self,
2276+
func: bytecode::IntrinsicFunction2,
2277+
arg1: PyObjectRef,
2278+
arg2: PyObjectRef,
2279+
vm: &VirtualMachine,
2280+
) -> PyResult {
2281+
match func {
2282+
bytecode::IntrinsicFunction2::SetTypeparamDefault => {
2283+
crate::stdlib::typing::set_typeparam_default(arg1, arg2, vm)
2284+
}
2285+
}
2286+
}
2287+
22472288
fn pop_multiple(&mut self, count: usize) -> crate::common::boxvec::Drain<'_, PyObjectRef> {
22482289
let stack_len = self.state.stack.len();
22492290
self.state.stack.drain(stack_len - count..)

0 commit comments

Comments
 (0)
0