Skip to content

Conversation

@youknowone
Copy link
Member

@youknowone youknowone commented Jan 20, 2026

Summary by CodeRabbit

  • Refactor
    • Aligned bytecode compiler with CPython 3.14 standards by removing custom opcodes and restructuring how context manager and subscript operations are compiled.
    • Updated instruction handling for with/async-with statements and item subscripting to follow Python standard conventions.
    • Enhanced special method resolution in bytecode generation.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 20, 2026

📝 Walkthrough

Walkthrough

This PR aligns RustPython's bytecode with CPython 3.14 by removing custom opcodes (BeforeWith, BeforeAsyncWith, BinarySubscr, BuildConstKeyMap), introducing a SpecialMethod enum for explicit context-manager method resolution, and unifying subscripting into BinaryOperator::Subscr across compilation and runtime execution.

Changes

Cohort / File(s) Summary
Spell-check Dictionary
.cspell.dict/cpython.txt
Added six CPython-related tokens (INCREF, inplace, Lshift, repr, Rshift, subscr) to the spell-check dictionary; no functional code changes.
Bytecode Type Definitions
crates/compiler-core/src/bytecode/oparg.rs
Introduced new public SpecialMethod enum with four variants (Enter, Exit, AEnter, AExit) and Display impl; extended BinaryOperator with Subscr = 26 variant.
Instruction Enum & Exports
crates/compiler-core/src/bytecode/instruction.rs, crates/compiler-core/src/bytecode.rs
Removed RustPython-specific opcodes (BeforeAsyncWith, BeforeWith, BinarySubscr, BuildConstKeyMap); changed LoadSpecial signature from arg: Arg<u32> to method: Arg<SpecialMethod>; added SpecialMethod to public re-exports.
Codegen & Compilation
crates/codegen/src/compile.rs
Replaced BinarySubscr with BinaryOp { op: BinaryOperator::Subscr } for subscripting contexts; replaced BeforeWith/BeforeAsyncWith with explicit LoadSpecial + stack manipulation (PushNull, Call) for context-manager method loading.
Runtime Execution
crates/vm/src/frame.rs
Removed instruction handlers for BeforeAsyncWith and BeforeWith; added LoadSpecial { method } handler to resolve and push bound context-manager methods; added BinaryOperator::Subscr dispatch to execute_bin_op.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~40 minutes

The changes span multiple compilation pipeline layers with significant structural modifications: removal of public opcodes, introduction of new enum types, updates to codegen emission patterns, and corresponding runtime execution changes. Verification requires checking consistency across codegen, bytecode representation, and VM execution paths.

Possibly related PRs

  • RustPython#6741: Directly conflicts with this PR by making overlapping changes to the bytecode Instruction enum and opcode discriminants.
  • RustPython#6317: Related through bytecode-level binary operator handling; this PR adds Subscr while the other unifies and extends BinaryOperator variants.
  • RustPython#6638: Modifies the same bytecode/instruction surface and VM handling for with-statements, implementing the BeforeWith/BeforeAsyncWith variants that this PR removes.

Suggested reviewers

  • ShaharNaveh

Poem

🐰 Hopping through bytecode with glee,
We've trimmed the opcodes, now 3.14-free!
LoadSpecial hops, subscripts align,
CPython's path becomes yours and mine! 🎯

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately identifies the primary changes: removal of BEFORE_WITH and BINARY_SUBSCR opcodes, which are the main public API removals across the codebase.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Contributor

📦 Library Dependencies

The following Lib/ modules were modified. Here are their dependencies:

Click to expand dependency information
[+] lib: cpython/Lib/_opcode_metadata.py
[-] test: cpython/Lib/test/test__opcode_metadata
soft_deps:
- [ ] _opcode_metadata

Legend:

  • [+] path exists, [-] path missing
  • [x] up-to-date, [ ] outdated
  • native: Rust/C extension modules

}),
];
// No RustPython-only opcodes anymore - all opcodes match CPython 3.14
let custom_ops: &[u8] = &[];
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🥳

@youknowone youknowone marked this pull request as ready for review January 20, 2026 17:09
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@crates/vm/src/frame.rs`:
- Around line 1234-1267: Update the user-facing TypeError message in the
Instruction::LoadSpecial handling so it uses "missing" instead of "missed":
locate the vm.new_type_error call inside the LoadSpecial match arm (in frame
handling where get_special_method returns None) and change the message string to
"'{}' object does not support the context manager protocol (missing {} method)"
to correct the grammar.

Comment on lines +1234 to +1267
Instruction::LoadSpecial { method } => {
// Stack effect: 0 (replaces TOS with bound method)
// Input: [..., obj]
// Output: [..., bound_method]
use crate::vm::PyMethod;
use bytecode::SpecialMethod;

let obj = self.pop_value();
let method_name = match method.get(arg) {
SpecialMethod::Enter => identifier!(vm, __enter__),
SpecialMethod::Exit => identifier!(vm, __exit__),
SpecialMethod::AEnter => identifier!(vm, __aenter__),
SpecialMethod::AExit => identifier!(vm, __aexit__),
};

let bound = match vm.get_special_method(&obj, method_name)? {
Some(PyMethod::Function { target, func }) => {
// Create bound method: PyBoundMethod(object=target, function=func)
crate::builtins::PyBoundMethod::new(target, func)
.into_ref(&vm.ctx)
.into()
}
Some(PyMethod::Attribute(bound)) => bound,
None => {
return Err(vm.new_type_error(format!(
"'{}' object does not support the context manager protocol (missed {} method)",
obj.class().name(),
method_name
)));
}
};
self.push_value(bound);
Ok(None)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Minor: Fix grammatical error in error message.

The error message uses "missed" (past tense verb) instead of "missing" (adjective). This is a minor user-facing text quality issue.

📝 Suggested fix
                 None => {
                     return Err(vm.new_type_error(format!(
-                        "'{}' object does not support the context manager protocol (missed {} method)",
+                        "'{}' object does not support the context manager protocol (missing {} method)",
                         obj.class().name(),
                         method_name
                     )));
                 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Instruction::LoadSpecial { method } => {
// Stack effect: 0 (replaces TOS with bound method)
// Input: [..., obj]
// Output: [..., bound_method]
use crate::vm::PyMethod;
use bytecode::SpecialMethod;
let obj = self.pop_value();
let method_name = match method.get(arg) {
SpecialMethod::Enter => identifier!(vm, __enter__),
SpecialMethod::Exit => identifier!(vm, __exit__),
SpecialMethod::AEnter => identifier!(vm, __aenter__),
SpecialMethod::AExit => identifier!(vm, __aexit__),
};
let bound = match vm.get_special_method(&obj, method_name)? {
Some(PyMethod::Function { target, func }) => {
// Create bound method: PyBoundMethod(object=target, function=func)
crate::builtins::PyBoundMethod::new(target, func)
.into_ref(&vm.ctx)
.into()
}
Some(PyMethod::Attribute(bound)) => bound,
None => {
return Err(vm.new_type_error(format!(
"'{}' object does not support the context manager protocol (missed {} method)",
obj.class().name(),
method_name
)));
}
};
self.push_value(bound);
Ok(None)
}
Instruction::LoadSpecial { method } => {
// Stack effect: 0 (replaces TOS with bound method)
// Input: [..., obj]
// Output: [..., bound_method]
use crate::vm::PyMethod;
use bytecode::SpecialMethod;
let obj = self.pop_value();
let method_name = match method.get(arg) {
SpecialMethod::Enter => identifier!(vm, __enter__),
SpecialMethod::Exit => identifier!(vm, __exit__),
SpecialMethod::AEnter => identifier!(vm, __aenter__),
SpecialMethod::AExit => identifier!(vm, __aexit__),
};
let bound = match vm.get_special_method(&obj, method_name)? {
Some(PyMethod::Function { target, func }) => {
// Create bound method: PyBoundMethod(object=target, function=func)
crate::builtins::PyBoundMethod::new(target, func)
.into_ref(&vm.ctx)
.into()
}
Some(PyMethod::Attribute(bound)) => bound,
None => {
return Err(vm.new_type_error(format!(
"'{}' object does not support the context manager protocol (missing {} method)",
obj.class().name(),
method_name
)));
}
};
self.push_value(bound);
Ok(None)
}
🤖 Prompt for AI Agents
In `@crates/vm/src/frame.rs` around lines 1234 - 1267, Update the user-facing
TypeError message in the Instruction::LoadSpecial handling so it uses "missing"
instead of "missed": locate the vm.new_type_error call inside the LoadSpecial
match arm (in frame handling where get_special_method returns None) and change
the message string to "'{}' object does not support the context manager protocol
(missing {} method)" to correct the grammar.

@youknowone youknowone merged commit a7f2351 into RustPython:main Jan 20, 2026
14 checks passed
@youknowone youknowone deleted the remove-before-with branch January 20, 2026 17:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants