-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Renewd DictUpdate instruction #6085
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -800,26 +800,40 @@ impl ExecutingFrame<'_> { | |||||||||||||||||||||||||||||||||||||||||
bytecode::Instruction::BuildMapForCall { size } => { | ||||||||||||||||||||||||||||||||||||||||||
self.execute_build_map_for_call(vm, size.get(arg)) | ||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||
bytecode::Instruction::DictUpdate => { | ||||||||||||||||||||||||||||||||||||||||||
let other = self.pop_value(); | ||||||||||||||||||||||||||||||||||||||||||
let dict = self | ||||||||||||||||||||||||||||||||||||||||||
.top_value() | ||||||||||||||||||||||||||||||||||||||||||
.downcast_ref::<PyDict>() | ||||||||||||||||||||||||||||||||||||||||||
.expect("exact dict expected"); | ||||||||||||||||||||||||||||||||||||||||||
bytecode::Instruction::DictUpdate { index } => { | ||||||||||||||||||||||||||||||||||||||||||
// Stack before: [..., dict, ..., source] (source at TOS) | ||||||||||||||||||||||||||||||||||||||||||
// Stack after: [..., dict, ...] (source consumed) | ||||||||||||||||||||||||||||||||||||||||||
// The dict to update is at position TOS-i (before popping source) | ||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||
let idx = index.get(arg); | ||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||
// Pop the source from TOS | ||||||||||||||||||||||||||||||||||||||||||
let source = self.pop_value(); | ||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||
// Get the dict to update (it's now at TOS-(i-1) after popping source) | ||||||||||||||||||||||||||||||||||||||||||
let dict = if idx <= 1 { | ||||||||||||||||||||||||||||||||||||||||||
// DICT_UPDATE 0 or 1: dict is at TOS (after popping source) | ||||||||||||||||||||||||||||||||||||||||||
self.top_value() | ||||||||||||||||||||||||||||||||||||||||||
} else { | ||||||||||||||||||||||||||||||||||||||||||
// DICT_UPDATE n: dict is at TOS-(n-1) | ||||||||||||||||||||||||||||||||||||||||||
self.nth_value(idx - 1) | ||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||
let dict = dict.downcast_ref::<PyDict>().expect("exact dict expected"); | ||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||
// For dictionary unpacking {**x}, x must be a mapping | ||||||||||||||||||||||||||||||||||||||||||
// Check if the object has the mapping protocol (keys method) | ||||||||||||||||||||||||||||||||||||||||||
if vm | ||||||||||||||||||||||||||||||||||||||||||
.get_method(other.clone(), vm.ctx.intern_str("keys")) | ||||||||||||||||||||||||||||||||||||||||||
.get_method(source.clone(), vm.ctx.intern_str("keys")) | ||||||||||||||||||||||||||||||||||||||||||
.is_none() | ||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||
return Err(vm.new_type_error(format!( | ||||||||||||||||||||||||||||||||||||||||||
"'{}' object is not a mapping", | ||||||||||||||||||||||||||||||||||||||||||
other.class().name() | ||||||||||||||||||||||||||||||||||||||||||
source.class().name() | ||||||||||||||||||||||||||||||||||||||||||
))); | ||||||||||||||||||||||||||||||||||||||||||
Comment on lines
826
to
833
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Don't mask attribute lookup errors when checking mapping protocol vm.get_method(...) returns Option<PyResult<_>>; using is_none() ignores Some(Err(e)) and turns it into a TypeError, hiding the real exception. Propagate lookup errors instead. - if vm
- .get_method(source.clone(), vm.ctx.intern_str("keys"))
- .is_none()
- {
- return Err(vm.new_type_error(format!(
- "'{}' object is not a mapping",
- source.class().name()
- )));
- }
+ match vm.get_method(source.clone(), vm.ctx.intern_str("keys")) {
+ Some(Ok(_)) => {}
+ Some(Err(e)) => return Err(e),
+ None => {
+ return Err(vm.new_type_error(format!(
+ "'{}' object is not a mapping",
+ source.class().name()
+ )));
+ }
+ } 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents
|
||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||
dict.merge_object(other, vm)?; | ||||||||||||||||||||||||||||||||||||||||||
dict.merge_object(source, vm)?; | ||||||||||||||||||||||||||||||||||||||||||
Ok(None) | ||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||
bytecode::Instruction::BuildSlice { step } => { | ||||||||||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Clarify
DictUpdate
index semantics and verify call sitesGood move making
DictUpdate
carryindex: Arg<u32>
; naming aligns withCopyItem
/Swap
.Please add a short doc comment clarifying:
index
is relative to (TOS before pop vs. after popping the source mapping).Also, since this changes the bytecode argument shape, ensure marshaled bytecode compatibility is addressed (e.g., version bump/invalidation or explicit handling when
index == 0
to preserve legacy behavior).Run this to find any stale patterns still matching/constructing the unit variant form:
I can draft the doc comment and add unit tests asserting stack effect and disassembly output once you confirm the intended “before/after pop” convention.
🏁 Script executed:
Length of output: 319276
Add documentation for
DictUpdate
index semantics & ensure marshaling compatibilityPlease update compiler/core/src/bytecode.rs around the
DictUpdate
variant (lines 667–672) as follows:index
is a 0-based offset to the dict on the stack before popping the source mapping. For example:index
field) will decode withindex == 0
; if you intend to break compatibility, bump the bytecode version or handleindex == 0
explicitly in tests.Next steps:
Instruction::DictUpdate { index }
yieldsstack_effect() == -1
fmt_dis()
printsDictUpdate { index }
DictUpdate
(without arg) and ensures it decodes toDictUpdate { index: 0 }
.🤖 Prompt for AI Agents