Skip to content

Commit 44a1b1d

Browse files
committed
ZeroArg
1 parent da5328f commit 44a1b1d

File tree

2 files changed

+41
-17
lines changed

2 files changed

+41
-17
lines changed

crates/codegen/src/compile.rs

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,6 @@ enum SuperCallType<'a> {
8484
self_arg: &'a Expr,
8585
},
8686
/// super() - implicit 0-argument form (uses __class__ cell)
87-
/// TODO: Enable after fixing __class__ cell handling in nested classes
88-
#[allow(dead_code)]
8987
ZeroArg,
9088
}
9189

@@ -715,14 +713,18 @@ impl Compiler {
715713
return None;
716714
}
717715

718-
// 6. "super" must be GlobalImplicit (not redefined locally)
716+
// 6. "super" must be GlobalImplicit (not redefined locally or at module level)
719717
let table = self.current_symbol_table();
720-
if let Some(symbol) = table.lookup("super") {
721-
if symbol.scope != SymbolScope::GlobalImplicit {
722-
return None;
723-
}
724-
} else {
725-
// super not found in symbol table - assume it's a global builtin
718+
if let Some(symbol) = table.lookup("super")
719+
&& symbol.scope != SymbolScope::GlobalImplicit
720+
{
721+
return None;
722+
}
723+
// Also check top-level scope to detect module-level shadowing
724+
if let Some(top_table) = self.symbol_table_stack.first()
725+
&& top_table.lookup("super").is_some()
726+
{
727+
return None;
726728
}
727729

728730
// 7. Check argument pattern
@@ -743,10 +745,26 @@ impl Compiler {
743745
}
744746
0 => {
745747
// 0-arg: super() - need __class__ cell and first parameter
746-
// TODO: 0-arg super() optimization is disabled due to __class__ cell issues
747-
// The __class__ cell handling in nested class definitions needs more work.
748-
// For now, fall back to regular super() call.
749-
None
748+
// Enclosing function should have at least one positional argument
749+
let info = self.code_stack.last()?;
750+
if info.metadata.argcount == 0 && info.metadata.posonlyargcount == 0 {
751+
return None;
752+
}
753+
754+
// Check if __class__ is available as a cell/free variable
755+
// The scope must be Free (from enclosing class) or have FREE_CLASS flag
756+
if let Some(symbol) = table.lookup("__class__") {
757+
if symbol.scope != SymbolScope::Free
758+
&& !symbol.flags.contains(SymbolFlags::FREE_CLASS)
759+
{
760+
return None;
761+
}
762+
} else {
763+
// __class__ not in symbol table, optimization not possible
764+
return None;
765+
}
766+
767+
Some(SuperCallType::ZeroArg)
750768
}
751769
_ => None, // 1 or 3+ args - not optimizable
752770
}
@@ -3494,12 +3512,14 @@ impl Compiler {
34943512
/// Determines if a variable should be CELL or FREE type
34953513
// = get_ref_type
34963514
fn get_ref_type(&self, name: &str) -> Result<SymbolScope, CodegenErrorType> {
3515+
let table = self.symbol_table_stack.last().unwrap();
3516+
34973517
// Special handling for __class__ and __classdict__ in class scope
3498-
if self.ctx.in_class && (name == "__class__" || name == "__classdict__") {
3518+
// This should only apply when we're actually IN a class body,
3519+
// not when we're in a method nested inside a class.
3520+
if table.typ == CompilerScope::Class && (name == "__class__" || name == "__classdict__") {
34993521
return Ok(SymbolScope::Cell);
35003522
}
3501-
3502-
let table = self.symbol_table_stack.last().unwrap();
35033523
match table.lookup(name) {
35043524
Some(symbol) => match symbol.scope {
35053525
SymbolScope::Cell => Ok(SymbolScope::Cell),

crates/compiler-core/src/bytecode/instruction.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use crate::{
66
Arg, BinaryOperator, BorrowedConstant, BuildSliceArgCount, ComparisonOperator, Constant,
77
ConvertValueOparg, InstrDisplayContext, IntrinsicFunction1, IntrinsicFunction2, Invert,
88
Label, MakeFunctionFlags, NameIdx, OpArg, RaiseKind, UnpackExArgs, decode_load_attr_arg,
9+
decode_load_super_attr_arg,
910
},
1011
marshal::MarshalError,
1112
};
@@ -349,6 +350,10 @@ impl TryFrom<u8> for Instruction {
349350
u8::from(Self::JumpIfNotExcMatch(Arg::marker())),
350351
u8::from(Self::SetExcInfo),
351352
u8::from(Self::Subscript),
353+
// LOAD_SUPER_* pseudo opcodes (136-138)
354+
u8::from(Self::LoadSuperMethod { idx: Arg::marker() }),
355+
u8::from(Self::LoadZeroSuperAttr { idx: Arg::marker() }),
356+
u8::from(Self::LoadZeroSuperMethod { idx: Arg::marker() }),
352357
];
353358

354359
// Pseudo opcodes (252-255)
@@ -632,7 +637,6 @@ impl Instruction {
632637
Self::LoadFromDictOrGlobals(_) => 0,
633638
Self::SetUpdate { .. } => 0,
634639
Self::MakeCell(_) => 0,
635-
Self::LoadSuperAttr { .. } => 0,
636640
Self::StoreFastStoreFast { .. } => 0,
637641
Self::PopJumpIfNone { .. } => 0,
638642
Self::PopJumpIfNotNone { .. } => 0,

0 commit comments

Comments
 (0)