Skip to content

Commit 28dff8a

Browse files
authored
Fix TypeParams, TypeAlias compile (#5862)
1 parent 0ef22ab commit 28dff8a

File tree

2 files changed

+34
-8
lines changed

2 files changed

+34
-8
lines changed

compiler/codegen/src/compile.rs

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1042,14 +1042,32 @@ impl Compiler<'_> {
10421042
)));
10431043
};
10441044
let name_string = name.id.to_string();
1045-
if type_params.is_some() {
1046-
self.push_symbol_table();
1047-
}
1048-
self.compile_expression(value)?;
1045+
1046+
// For PEP 695 syntax, we need to compile type_params first
1047+
// so that they're available when compiling the value expression
10491048
if let Some(type_params) = type_params {
1049+
self.push_symbol_table();
1050+
1051+
// Compile type params first to define T1, T2, etc.
10501052
self.compile_type_params(type_params)?;
1053+
// Stack now has type_params tuple at top
1054+
1055+
// Compile value expression (can now see T1, T2)
1056+
self.compile_expression(value)?;
1057+
// Stack: [type_params_tuple, value]
1058+
1059+
// We need [value, type_params_tuple] for TypeAlias instruction
1060+
emit!(self, Instruction::Rotate2);
1061+
10511062
self.pop_symbol_table();
1063+
} else {
1064+
// No type params - push value first, then None (not empty tuple)
1065+
self.compile_expression(value)?;
1066+
// Push None for type_params (matching CPython)
1067+
self.emit_load_const(ConstantData::None);
10521068
}
1069+
1070+
// Push name last
10531071
self.emit_load_const(ConstantData::Str {
10541072
value: name_string.clone().into(),
10551073
});

vm/src/frame.rs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1266,10 +1266,18 @@ impl ExecutingFrame<'_> {
12661266
}
12671267
bytecode::Instruction::TypeAlias => {
12681268
let name = self.pop_value();
1269-
let type_params: PyTupleRef = self
1270-
.pop_value()
1271-
.downcast()
1272-
.map_err(|_| vm.new_type_error("Type params must be a tuple."))?;
1269+
let type_params_obj = self.pop_value();
1270+
1271+
// CPython allows None or tuple for type_params
1272+
let type_params: PyTupleRef = if vm.is_none(&type_params_obj) {
1273+
// If None, use empty tuple (matching CPython's behavior)
1274+
vm.ctx.empty_tuple.clone()
1275+
} else {
1276+
type_params_obj
1277+
.downcast()
1278+
.map_err(|_| vm.new_type_error("Type params must be a tuple."))?
1279+
};
1280+
12731281
let value = self.pop_value();
12741282
let type_alias = typing::TypeAliasType::new(name, type_params, value);
12751283
self.push_value(type_alias.into_ref(&vm.ctx).into());

0 commit comments

Comments
 (0)