Skip to content

Commit 1373ebb

Browse files
committed
retry
1 parent 5db7ccc commit 1373ebb

File tree

3 files changed

+49
-41
lines changed

3 files changed

+49
-41
lines changed

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: 26 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -932,6 +932,21 @@ mod builtins {
932932
))
933933
})?;
934934

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

@@ -943,48 +958,21 @@ mod builtins {
943958
)?;
944959
}
945960

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-
};
961+
// Remove .type_params from namespace before creating the class
962+
namespace
963+
.as_object()
964+
.del_item(vm.ctx.intern_str(".type_params"), vm)
965+
.ok();
976966

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

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)?;
970+
// For PEP 695 classes, set __type_params__ on the class from the function
971+
let function_obj: PyObjectRef = function.clone().into();
972+
if let Ok(type_params) = function_obj.get_attr(identifier!(vm, __type_params__), vm) {
973+
if let Ok(type_params_tuple) = type_params.clone().downcast::<PyTuple>() {
974+
if !type_params_tuple.is_empty() {
975+
class.set_attr(identifier!(vm, __type_params__), type_params, vm)?;
988976
}
989977
}
990978
}

0 commit comments

Comments
 (0)