Skip to content

Make OpArgType::from_op_arg to return a Result<Self, MarshalError>#6914

Merged
youknowone merged 1 commit intoRustPython:mainfrom
ShaharNaveh:argtype-return-result
Jan 31, 2026
Merged

Make OpArgType::from_op_arg to return a Result<Self, MarshalError>#6914
youknowone merged 1 commit intoRustPython:mainfrom
ShaharNaveh:argtype-return-result

Conversation

@ShaharNaveh
Copy link
Contributor

@ShaharNaveh ShaharNaveh commented Jan 31, 2026

This will allow us to use num_enum crate with a custom error, I'll do it in a followup PR

Summary by CodeRabbit

  • Refactor
    • Improved internal error handling in the compiler's bytecode instruction processing to provide more detailed error information when invalid bytecode is encountered.

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

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 31, 2026

📝 Walkthrough

Walkthrough

A refactoring of error handling in bytecode instruction processing, converting return types from Option<T> to Result<T, MarshalError> across the OpArgType trait and Arg<T>::try_get method to provide more descriptive error information on invalid bytecode.

Changes

Cohort / File(s) Summary
OpArgType trait refactoring
crates/compiler-core/src/bytecode/oparg.rs
Changed from_op_arg return type from Option<Self> to Result<Self, MarshalError> in trait definition and all implementations (ConvertValueOparg, u32, bool, Label, MakeFunctionFlags, BuildSliceArgCount, UnpackExArgs, and macro-generated enums). Invalid bytecode conditions now return Err(MarshalError::InvalidBytecode) instead of None.
Arg type getter
crates/compiler-core/src/bytecode/instruction.rs
Updated Arg<T>::try_get method signature to return Result<T, MarshalError> instead of Option<T>, delegating to the updated T::from_op_arg implementation.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

  • RustPython/RustPython#6703: This PR directly modifies the same OpArgType::from_op_arg trait method and Arg<T>::try_get implementation, converting their return types from Option to Result<_, MarshalError>.

Suggested reviewers

  • youknowone

Poem

🐰 From Options to Results, we now declare,
Error types flowing with much greater care,
MarshalError whispers of bytecode gone wrong,
No more silent Nones in our instruction song!
The bytecode now speaks what went awry, 🎯

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title accurately reflects the main change: converting OpArgType::from_op_arg to return Result<Self, MarshalError> instead of Option. This is clearly the primary objective of the changeset across both modified files.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

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

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

@ShaharNaveh ShaharNaveh changed the title Make to_oparg to return a Result<Self, MarshalError> Make OpArgType::from_op_arg to return a Result<Self, MarshalError> Jan 31, 2026
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/compiler-core/src/bytecode/oparg.rs`:
- Around line 640-645: from_op_arg for UnpackExArgs currently truncates high
bytes via to_le_bytes; instead validate that the upper two bytes of x are zero
before constructing UnpackExArgs to avoid accepting invalid bytecode: check (x
>> 16) == 0 (or inspect bytes[2..]) and return an appropriate MarshalError if
non-zero, otherwise proceed to extract before and after and return
Ok(Self{before, after}); reference UnpackExArgs, OpArgType::from_op_arg, and
MarshalError to locate where to add the check and error return.

Comment on lines 640 to 645
impl OpArgType for UnpackExArgs {
#[inline(always)]
fn from_op_arg(x: u32) -> Option<Self> {
fn from_op_arg(x: u32) -> Result<Self, MarshalError> {
let [before, after, ..] = x.to_le_bytes();
Some(Self { before, after })
Ok(Self { before, after })
}
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

Validate upper bytes for UnpackExArgs to avoid accepting invalid bytecode.
Right now values with non-zero high bytes are silently truncated, which defeats the new error reporting.

🛠️ Suggested fix
 fn from_op_arg(x: u32) -> Result<Self, MarshalError> {
-    let [before, after, ..] = x.to_le_bytes();
-    Ok(Self { before, after })
+    let [before, after, hi1, hi2] = x.to_le_bytes();
+    if hi1 != 0 || hi2 != 0 {
+        return Err(MarshalError::InvalidBytecode);
+    }
+    Ok(Self { before, after })
 }
📝 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
impl OpArgType for UnpackExArgs {
#[inline(always)]
fn from_op_arg(x: u32) -> Option<Self> {
fn from_op_arg(x: u32) -> Result<Self, MarshalError> {
let [before, after, ..] = x.to_le_bytes();
Some(Self { before, after })
Ok(Self { before, after })
}
impl OpArgType for UnpackExArgs {
#[inline(always)]
fn from_op_arg(x: u32) -> Result<Self, MarshalError> {
let [before, after, hi1, hi2] = x.to_le_bytes();
if hi1 != 0 || hi2 != 0 {
return Err(MarshalError::InvalidBytecode);
}
Ok(Self { before, after })
}
}
🤖 Prompt for AI Agents
In `@crates/compiler-core/src/bytecode/oparg.rs` around lines 640 - 645,
from_op_arg for UnpackExArgs currently truncates high bytes via to_le_bytes;
instead validate that the upper two bytes of x are zero before constructing
UnpackExArgs to avoid accepting invalid bytecode: check (x >> 16) == 0 (or
inspect bytes[2..]) and return an appropriate MarshalError if non-zero,
otherwise proceed to extract before and after and return Ok(Self{before,
after}); reference UnpackExArgs, OpArgType::from_op_arg, and MarshalError to
locate where to add the check and error return.

@youknowone youknowone merged commit 988b8b8 into RustPython:main Jan 31, 2026
33 of 35 checks passed
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