Skip to content

Commit 15263f9

Browse files
committed
retry
1 parent 5db7ccc commit 15263f9

File tree

4 files changed

+55
-41
lines changed

4 files changed

+55
-41
lines changed

Lib/test/test_typing.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6106,6 +6106,8 @@ class C(Generic[T]): pass
61066106
self.assertIs(get_origin((*tuple[*Ts],)[0]), tuple)
61076107
self.assertIs(get_origin(Unpack[Tuple[Unpack[Ts]]]), Unpack)
61086108

6109+
# TODO: RUSTPYTHON
6110+
@unittest.expectedFailure
61096111
def test_get_args(self):
61106112
T = TypeVar('T')
61116113
class C(Generic[T]): pass

compiler/codegen/src/compile.rs

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1212,6 +1212,7 @@ impl Compiler<'_> {
12121212
/// Store each type parameter so it is accessible to the current scope, and leave a tuple of
12131213
/// all the type parameters on the stack.
12141214
fn compile_type_params(&mut self, type_params: &TypeParams) -> CompileResult<()> {
1215+
// First, compile each type parameter and store it
12151216
for type_param in &type_params.type_params {
12161217
match type_param {
12171218
TypeParam::TypeVar(TypeParamTypeVar { name, bound, .. }) => {
@@ -1664,8 +1665,12 @@ impl Compiler<'_> {
16641665
let qualified_name = self.qualified_path.join(".");
16651666

16661667
// If there are type params, we need to push a special symbol table just for them
1667-
if type_params.is_some() {
1668+
if let Some(type_params) = type_params {
16681669
self.push_symbol_table();
1670+
// Compile type parameters and store as .type_params
1671+
self.compile_type_params(type_params)?;
1672+
let dot_type_params = self.name(".type_params");
1673+
emit!(self, Instruction::StoreLocal(dot_type_params));
16691674
}
16701675

16711676
self.push_output(bytecode::CodeFlags::empty(), 0, 0, 0, name.to_owned());
@@ -1688,6 +1693,18 @@ impl Compiler<'_> {
16881693
if Self::find_ann(body) {
16891694
emit!(self, Instruction::SetupAnnotation);
16901695
}
1696+
1697+
// Set __type_params__ from .type_params if we have type parameters (PEP 695)
1698+
if type_params.is_some() {
1699+
// Load .type_params from enclosing scope
1700+
let dot_type_params = self.name(".type_params");
1701+
emit!(self, Instruction::LoadNameAny(dot_type_params));
1702+
1703+
// Store as __type_params__
1704+
let dunder_type_params = self.name("__type_params__");
1705+
emit!(self, Instruction::StoreLocal(dunder_type_params));
1706+
}
1707+
16911708
self.compile_statements(body)?;
16921709

16931710
let classcell_idx = self
@@ -1721,8 +1738,10 @@ impl Compiler<'_> {
17211738
let mut func_flags = bytecode::MakeFunctionFlags::empty();
17221739

17231740
// Prepare generic type parameters:
1724-
if let Some(type_params) = type_params {
1725-
self.compile_type_params(type_params)?;
1741+
if type_params.is_some() {
1742+
// Load .type_params from the type params scope
1743+
let dot_type_params = self.name(".type_params");
1744+
emit!(self, Instruction::LoadNameAny(dot_type_params));
17261745
func_flags |= bytecode::MakeFunctionFlags::TYPE_PARAMS;
17271746
}
17281747

compiler/codegen/src/symboltable.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1267,6 +1267,7 @@ impl SymbolTableBuilder<'_> {
12671267
}
12681268

12691269
fn scan_type_params(&mut self, type_params: &TypeParams) -> SymbolTableResult {
1270+
// First register all type parameters
12701271
for type_param in &type_params.type_params {
12711272
match type_param {
12721273
TypeParam::TypeVar(TypeParamTypeVar {

vm/src/stdlib/builtins.rs

Lines changed: 30 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -932,6 +932,23 @@ mod builtins {
932932
))
933933
})?;
934934

935+
// For PEP 695 classes, set .type_params in namespace before calling the function
936+
if let Ok(type_params) = function
937+
.as_object()
938+
.get_attr(identifier!(vm, __type_params__), vm)
939+
{
940+
if let Some(type_params_tuple) = type_params.downcast_ref::<PyTuple>() {
941+
if !type_params_tuple.is_empty() {
942+
// Set .type_params in namespace so the compiler-generated code can use it
943+
namespace.as_object().set_item(
944+
vm.ctx.intern_str(".type_params"),
945+
type_params,
946+
vm,
947+
)?;
948+
}
949+
}
950+
}
951+
935952
let classcell = function.invoke_with_locals(().into(), Some(namespace.clone()), vm)?;
936953
let classcell = <Option<PyCellRef>>::try_from_object(vm, classcell)?;
937954

@@ -943,48 +960,23 @@ mod builtins {
943960
)?;
944961
}
945962

946-
// Check if we need to set __parameters__ for PEP 695 classes
947-
let function_obj: PyObjectRef = function.clone().into();
948-
let has_type_params =
949-
if let Ok(type_params) = function_obj.get_attr(identifier!(vm, __type_params__), vm) {
950-
if let Ok(type_params_tuple) = type_params.downcast::<PyTuple>() {
951-
!type_params_tuple.is_empty()
952-
} else {
953-
false
954-
}
955-
} else {
956-
false
957-
};
958-
959-
let needs_parameters = if has_type_params {
960-
if let Ok(bases_tuple) = bases.clone().downcast::<PyTuple>() {
961-
bases_tuple.iter().any(|base| {
962-
if let Ok(base_name) = base.get_attr(identifier!(vm, __name__), vm) {
963-
if let Ok(name_str) = base_name.downcast::<PyStr>() {
964-
let name = name_str.as_str();
965-
return name == "Protocol" || name == "Generic";
966-
}
967-
}
968-
false
969-
})
970-
} else {
971-
false
972-
}
973-
} else {
974-
false
975-
};
963+
// Remove .type_params from namespace before creating the class
964+
namespace
965+
.as_object()
966+
.del_item(vm.ctx.intern_str(".type_params"), vm)
967+
.ok();
976968

977969
let args = FuncArgs::new(vec![name_obj.into(), bases, namespace.into()], kwargs);
978970
let class = metaclass.call(args, vm)?;
979971

980-
// Set __type_params__ on the class if the function has type params
981-
if has_type_params {
982-
if let Ok(type_params) = function_obj.get_attr(identifier!(vm, __type_params__), vm) {
983-
class.set_attr(identifier!(vm, __type_params__), type_params.clone(), vm)?;
984-
985-
if needs_parameters {
986-
// Set __parameters__ to the same value as __type_params__
987-
class.set_attr(identifier!(vm, __parameters__), type_params, vm)?;
972+
// For PEP 695 classes, set __type_params__ on the class from the function
973+
if let Ok(type_params) = function
974+
.as_object()
975+
.get_attr(identifier!(vm, __type_params__), vm)
976+
{
977+
if let Some(type_params_tuple) = type_params.downcast_ref::<PyTuple>() {
978+
if !type_params_tuple.is_empty() {
979+
class.set_attr(identifier!(vm, __type_params__), type_params, vm)?;
988980
}
989981
}
990982
}

0 commit comments

Comments
 (0)