Skip to content

stdlib: complete copy, enum, and weakref compatibility - #721

Closed
youknowone wants to merge 1 commit into
mainfrom
agent/stdlib-weakref
Closed

youknowone wants to merge 1 commit into
mainfrom
agent/stdlib-weakref

Conversation

@youknowone

@youknowone youknowone commented Jul 22, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • implement _weakref._remove_dead_weakref and public weakref type metadata
  • preserve recursive comparison safety and metaclass repr/delattr semantics needed by copy and enum
  • preserve builtin-subclass attribute identity and stable type __name__/__qualname__ objects
  • make LOAD_LOCALS retain custom metaclass __prepare__ mappings, matching PyPy
  • add focused copy and enum stdlib regression snippets

Validation

  • PYRE_JIT=0 target/debug/pyre-dynasm -m test test_enum — 1,081 tests successful
  • test_copy.py — 81 passed
  • weakref mapping/module groups — 29 passed
  • stdlib copy/enum/weakref snippets passed
  • cargo check --features dynasm
  • cargo test --features dynasm
  • python pyre/check.py: cranelift 248/248, wasm 247/247; dynasm 247/248 with the existing nested_loop performance gate exceeding 2x PyPy (all correctness runs passed)

Summary by CodeRabbit

  • Bug Fixes

    • Improved compatibility for class attributes, including __doc__, __name__, and __qualname__.
    • Corrected descriptor precedence and custom namespace handling during class creation.
    • Improved metaclass-controlled repr() and str() behavior.
    • Fixed weak-reference type names and cleanup behavior.
    • Corrected integer and float handling for subclasses.
    • Added safer recursion handling for comparisons involving recursive objects.
  • Tests

    • Added coverage for standard-library copy, enum, and weakref behavior.

@coderabbitai

coderabbitai Bot commented Jul 22, 2026 •

Copy link
Copy Markdown

Review Change Stack

Walkthrough

Changes

Runtime semantics and compatibility

Layer / File(s) Summary
Class metadata and class construction
pyre/pyre-object/src/typeobject.rs, pyre/pyre-interpreter/src/{builtins.rs,call.rs,typedef.rs,eval.rs}, pyre/pyre-jit/src/eval.rs
Class creation and type objects now preserve cached __name__, __qualname__, and __doc__ objects, while retaining custom namespace and subclass initialization behavior.
Attribute and representation dispatch
pyre/pyre-interpreter/src/{baseobjspace.rs,display.rs,builtins.rs}
Attribute lookup, deletion, descriptor precedence, and metaclass-based representation dispatch follow updated type and object semantics.
Weakref cleanup and recursive operations
pyre/pyre-interpreter/src/module/_weakref/*, pyre/pyre-interpreter/src/objspace/descroperation.rs, pyre/extra_tests/snippets/{stdlib_copy.py,stdlib_weakref.py}
Weakref names and subtype detection are updated, dead weakref removal is functional, and recursive comparisons receive stack protection with standard-library checks.
Exact-type numeric unboxing
pyre/pyre-interpreter/src/objspace/std/mapdict.rs, pyre/extra_tests/snippets/stdlib_enum.py
Integer and float unboxing now requires exact native types, including preservation checks for float subclasses.
Enum behavior compatibility
pyre/extra_tests/snippets/stdlib_enum.py
Enum, flag, descriptor, metaclass representation, and type-name identity behaviors are exercised by a self-checking snippet.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related issues

  • youknowone/pyre#205 — Covers overlapping heap-type metadata, GC handling, and weakref API work.

Possibly related PRs

Suggested reviewers: lifthrasiir

Poem

A rabbit hops through types anew,
With cached names and weakrefs too.
Enums march, recursive lists spin,
Exact floats keep their kin.
“stdlib copy ok!” we cheer—
The runtime grows more Pyre-ly clear.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main compatibility work across copy, enum, and weakref without being misleading.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch agent/stdlib-weakref
⚔️ Resolve merge conflicts
  • Resolve merge conflict in branch agent/stdlib-weakref

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.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 258a21607f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

};
}
}
crate::builtins::type_new_set_doc(class_ns)?;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Avoid validating slots before metaclass dispatch

Because this runs before the if let Some(w_metaclass) branch, a class whose custom metaclass consumes the namespace itself now fails during __build_class__ if __slots__ contains non-string/invalid entries: type_new_set_doc propagates collect_slot_names(...)? instead of leaving slot validation to type.__new__. In that scenario CPython/PyPy pass the namespace to the metaclass unchanged, so gate this validation to the default/type construction path or avoid propagating slot errors before custom metaclass dispatch.

AGENTS.md reference: AGENTS.md:L194-L195

Useful? React with 👍 / 👎.

{
return Ok(None);
}
let result = crate::builtins::call_and_check(method, &[obj])?;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Bind metaclass repr descriptors before calling

When a metaclass supplies __repr__ through a descriptor such as @staticmethod, @classmethod, or a custom __get__, this raw call passes the class object as an explicit argument instead of first binding the descriptor and then calling it with no arguments. CPython/PyPy special-method lookup applies the descriptor protocol here, so a no-arg staticmethod metaclass __repr__ should work but this path raises; use the existing get_and_call_function(method, obj, metaclass, &[]) shape.

AGENTS.md reference: AGENTS.md:L194-L195

Useful? React with 👍 / 👎.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pyre/pyre-interpreter/src/display.rs`:
- Around line 521-527: Update the new metaclass __repr__ branch in the display
function to avoid w_str_get_value(result), which panics on lone surrogates.
Reuse the WTF-8-safe conversion pattern from py_repr_wtf8 and the
backslashreplace-style fallback used by builtin_subclass_dunder, preserving the
existing successful __repr__ return behavior.

In `@pyre/pyre-interpreter/src/module/_weakref/interp__weakref.rs`:
- Around line 872-874: Replace the separate finditem and delitem_slot calls in
the weakref deletion flow with the atomic delitem_if_value_is or
nondescr_delitem_if_value_is helper, using backing, key, and stored so the value
check and deletion cannot be separated by re-entrant code.

In `@pyre/pyre-interpreter/src/objspace/std/mapdict.rs`:
- Around line 2014-2034: Update is_unboxable_int to explicitly reject bool
values before the bootstrap fallback, using the existing pyre_object::is_bool
check. Preserve the current exact-int and uninitialized-type handling for
non-bool integer objects.

In `@pyre/pyre-object/src/typeobject.rs`:
- Around line 807-820: Update w_type_get_name_obj and w_type_get_qualname_obj so
each lazy assignment to the GC-tracked w_name or w_qualname field is immediately
followed by crate::gc_hook::try_gc_write_barrier(obj as *mut u8). Leave the
existing caching and return behavior unchanged.
- Around line 848-853: Prevent lone-surrogate __qualname__ values from reaching
w_type_set_qualname by adding check_surrogate validation in
type_new_take_qualname at pyre/pyre-interpreter/src/builtins.rs:3655-3670 and
the __qualname__ branch of object_setattr at
pyre/pyre-interpreter/src/baseobjspace.rs:8611-8624, before calling the setter.
Update w_type_set_qualname in pyre/pyre-object/src/typeobject.rs:848-853 only as
needed to preserve this contract, ensuring valid strings are stored unchanged
and invalid values return an error instead of panicking.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: ab840aed-549c-45db-a2f9-0a4d6b41fc7a

📥 Commits

Reviewing files that changed from the base of the PR and between 9df4c18 and 258a216.

📒 Files selected for processing (15)
  • pyre/extra_tests/snippets/stdlib_copy.py
  • pyre/extra_tests/snippets/stdlib_enum.py
  • pyre/extra_tests/snippets/stdlib_weakref.py
  • pyre/pyre-interpreter/src/baseobjspace.rs
  • pyre/pyre-interpreter/src/builtins.rs
  • pyre/pyre-interpreter/src/call.rs
  • pyre/pyre-interpreter/src/display.rs
  • pyre/pyre-interpreter/src/eval.rs
  • pyre/pyre-interpreter/src/module/_weakref/interp__weakref.rs
  • pyre/pyre-interpreter/src/module/_weakref/mod.rs
  • pyre/pyre-interpreter/src/objspace/descroperation.rs
  • pyre/pyre-interpreter/src/objspace/std/mapdict.rs
  • pyre/pyre-interpreter/src/typedef.rs
  • pyre/pyre-jit/src/eval.rs
  • pyre/pyre-object/src/typeobject.rs

Comment on lines +521 to +527
// A class object is an instance of its metaclass. PyPy's
// `space.repr` therefore resolves `__repr__` on that metaclass before
// `type`'s native `<class ...>` representation. This is observable
// for EnumType and any user metaclass defining `__repr__`.
if let Some(result) = type_metaclass_dunder_obj(obj, "__repr__")? {
return Ok(pyre_object::w_str_get_value(result).to_string());
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

New metaclass __repr__ branch panics on a lone-surrogate result.

pyre_object::w_str_get_value(result) panics if the metaclass's __repr__ returns a str containing a lone surrogate. py_repr_wtf8 right above handles the identical situation safely via w_str_get_wtf8(...).to_wtf8_buf(). This mirrors two other pre-existing (unchanged) __repr__ dispatch sites later in this same function that have the same limitation, so it's a narrow addition to an existing, broader gap rather than a novel regression — but it's a real, easily-triggered crash (define a metaclass whose __repr__ returns a lone-surrogate string) worth closing here since the fix is a one-line swap to the WTF-8-safe path plus a backslashreplace-style fallback (as already done for builtin_subclass_dunder).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pyre/pyre-interpreter/src/display.rs` around lines 521 - 527, Update the new
metaclass __repr__ branch in the display function to avoid
w_str_get_value(result), which panics on lone surrogates. Reuse the WTF-8-safe
conversion pattern from py_repr_wtf8 and the backslashreplace-style fallback
used by builtin_subclass_dunder, preserving the existing successful __repr__
return behavior.

Comment on lines +872 to +874
if crate::baseobjspace::finditem(backing, key)? == Some(stored) {
crate::baseobjspace::delitem_slot(backing, key)?;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Locate existing conditional dictionary-deletion support before porting one.
ast-grep outline pyre/pyre-interpreter/src --items all --type function --match 'delitem'

rg -n -C 3 \
  'delitem_if_value_is|nondescr_delitem_if_value_is|dict_delitem|delitem_slot' \
  pyre/pyre-interpreter/src

Repository: youknowone/pyre

Length of output: 19676


🏁 Script executed:

rg -n -C 4 'nondescr_delitem_if_value_is|delitem_if_value_is|w_dict_delitem_if_value_is|delitem_slot\(backing, key\)' pyre/pyre-interpreter/src

Repository: youknowone/pyre

Length of output: 2682


🏁 Script executed:

ast-grep outline pyre/pyre-interpreter/src/baseobjspace.rs --match 'finditem' --view expanded

rg -n -C 3 'nondescr_delitem_if_value_is|delitem_if_value_is|value_is|finditem\(|delitem_slot\(' pyre/pyre-interpreter/src/baseobjspace.rs pyre/pyre-interpreter/src/objspace pyre/pyre-interpreter/src/module/_weakref/interp__weakref.rs

Repository: youknowone/pyre

Length of output: 5079


Use the atomic weakref-delete helper here. finditem(backing, key) followed by delitem_slot(backing, key) can re-enter user code and let backing change between the check and delete; route this through the delitem_if_value_is / nondescr_delitem_if_value_is path instead.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pyre/pyre-interpreter/src/module/_weakref/interp__weakref.rs` around lines
872 - 874, Replace the separate finditem and delitem_slot calls in the weakref
deletion flow with the atomic delitem_if_value_is or
nondescr_delitem_if_value_is helper, using backing, key, and stored so the value
check and deletion cannot be separated by re-entrant code.

Source: Coding guidelines

Comment on lines 2014 to +2034
unsafe fn is_unboxable_int(w_value: PyObjectRef) -> bool {
// Early-return control flow rather than `if c { false } else { x }`, which
// can become a `!c && x` (a `bool_not`) that majit-translate cannot lower.
if unsafe { pyre_object::is_bool(w_value) } {
if !unsafe { pyre_object::is_int(w_value) } {
return false;
}
let exact = crate::typedef::gettypeobject(&pyre_object::INT_TYPE);
if exact.is_null() {
// Interpreter-only unit tests may exercise mapdict before the app-level
// type registry is initialized. A native int with no class stamp is
// the bootstrap representation of that same exact type.
if pyre_object::tagged_int::CAN_BE_TAGGED
&& unsafe { pyre_object::tagged_int::is_tagged_int(w_value) }
{
return true;
}
return unsafe { (*w_value).w_class.is_null() };
}
let Some(actual) = crate::typedef::r#type(w_value) else {
return false;
};
std::ptr::eq(actual, exact)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Confirm pyre_object::is_bool exists and its signature matches is_int/is_float.
rg -n 'pub unsafe fn is_bool' pyre/pyre-object/src

Repository: youknowone/pyre

Length of output: 241


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- mapdict.rs around is_unboxable_int ---'
sed -n '2004,2038p' pyre/pyre-interpreter/src/objspace/std/mapdict.rs

echo
echo '--- pyobject.rs around is_int/is_bool/is_float ---'
sed -n '1118,1160p' pyre/pyre-object/src/pyobject.rs

echo
echo '--- typedef.rs around r#type docs ---'
rg -n -A8 -B4 'pub unsafe fn r#type|RODATA statics|init_typeobjects' pyre/pyre-object/src/typedef.rs

Repository: youknowone/pyre

Length of output: 3336


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- typedef.rs search for bootstrap statics and null w_class ---'
rg -n -A12 -B6 'True|False|RODATA|null w_class|init_typeobjects|before init_typeobjects|SIGBUS' pyre/pyre-object/src/typedef.rs pyre/pyre-object/src/pyobject.rs

echo
echo '--- bool/int constructors and singleton layout ---'
rg -n -A10 -B4 'BOOL_TYPE|INT_TYPE|w_class|ob_type' pyre/pyre-object/src/pyobject.rs pyre/pyre-object/src/typedef.rs

echo
echo '--- mapdict pick_unbox_type and value_has_unbox_type ---'
sed -n '2084,2100p' pyre/pyre-interpreter/src/objspace/std/mapdict.rs
sed -n '2624,2642p' pyre/pyre-interpreter/src/objspace/std/mapdict.rs

Repository: youknowone/pyre

Length of output: 50371


🏁 Script executed:

#!/bin/bash
set -euo pipefail

wc -l pyre/pyre-object/src/typedef.rs
rg -n 'True|False|Ellipsis|NotImplemented|RODATA|w_class' pyre/pyre-object/src/typedef.rs

Repository: youknowone/pyre

Length of output: 282


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- value_has_unbox_type and pick_unbox_type ---'
sed -n '2088,2100p' pyre/pyre-interpreter/src/objspace/std/mapdict.rs
sed -n '2624,2640p' pyre/pyre-interpreter/src/objspace/std/mapdict.rs

echo
echo '--- find callers of is_unboxable_int ---'
rg -n -A4 -B4 'is_unboxable_int\(' pyre/pyre-interpreter/src/objspace/std/mapdict.rs pyre/pyre-interpreter/src/objspace/std

echo
echo '--- search for explicit bool handling in mapdict unbox logic ---'
rg -n -A3 -B3 'is_bool|BOOL_TYPE|bool' pyre/pyre-interpreter/src/objspace/std/mapdict.rs

Repository: youknowone/pyre

Length of output: 14401


Bootstrap bool values are still misclassified as unboxable int. At pyre/pyre-interpreter/src/objspace/std/mapdict.rs:2014-2034, is_int() also matches bool, and the exact.is_null() fallback only checks w_class.is_null(). True/False are bootstrap singletons with null w_class, so this branch accepts them as ints before init_typeobjects(). Keep an explicit is_bool() exclusion here as well.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pyre/pyre-interpreter/src/objspace/std/mapdict.rs` around lines 2014 - 2034,
Update is_unboxable_int to explicitly reject bool values before the bootstrap
fallback, using the existing pyre_object::is_bool check. Preserve the current
exact-int and uninitialized-type handling for non-bool integer objects.

Source: Coding guidelines

Comment on lines +807 to +820
/// Return the stable app-level `type.__name__` object.
pub unsafe fn w_type_get_name_obj(obj: PyObjectRef) -> PyObjectRef {
let t = &mut *(obj as *mut W_TypeObject);
if t.w_name.is_null() {
let full = &*t.name;
let bare = if t.flag_heaptype {
full.as_str()
} else {
full.rsplit('.').next().unwrap_or(full)
};
t.w_name = crate::w_str_new(bare);
}
t.w_name
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🔴 Critical | ⚡ Quick win

Missing GC write barrier when lazily caching w_name/w_qualname.

Both w_type_get_name_obj and w_type_get_qualname_obj mutate a PyObjectRef field on W_TypeObject (t.w_name = crate::w_str_new(bare); / t.w_qualname = crate::w_str_new(&*t.qualname);) but never call crate::gc_hook::try_gc_write_barrier(obj as *mut u8) afterward. Every other place in this file that stores into these GC-tracked fields post-construction (w_type_set_name, w_type_set_qualname, and w_type_new's own construction path) explicitly triggers the barrier. type_object_custom_trace (pyre-jit/src/eval.rs) now forwards w_name/w_qualname as real GC edges, which confirms these are genuine GC references requiring barrier protection on old-gen objects.

Since a heap type is typically old-gen (w_type_new's gc_managed path) while w_str_new(bare) likely allocates a fresh (young) string, storing it into t.w_name without a barrier means a minor collection may never re-scan this type object, so the freshly cached string can be collected while t.w_name still points at it — a latent use-after-free that would only surface under GC pressure. Note that stdlib_enum.py's Custom.__name__ is Custom.__name__ identity assertion exercises exactly this cached path but wouldn't reliably catch this bug since it needs a GC cycle between the two reads to manifest.
[critical_issue_confidence: high]

🛡️ Proposed fix
 pub unsafe fn w_type_get_name_obj(obj: PyObjectRef) -> PyObjectRef {
     let t = &mut *(obj as *mut W_TypeObject);
     if t.w_name.is_null() {
         let full = &*t.name;
         let bare = if t.flag_heaptype {
             full.as_str()
         } else {
             full.rsplit('.').next().unwrap_or(full)
         };
         t.w_name = crate::w_str_new(bare);
+        crate::gc_hook::try_gc_write_barrier(obj as *mut u8);
     }
     t.w_name
 }
 pub unsafe fn w_type_get_qualname_obj(obj: PyObjectRef) -> PyObjectRef {
     let t = &mut *(obj as *mut W_TypeObject);
     if t.w_qualname.is_null() {
         t.w_qualname = crate::w_str_new(&*t.qualname);
+        crate::gc_hook::try_gc_write_barrier(obj as *mut u8);
     }
     t.w_qualname
 }

Also applies to: 839-846

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pyre/pyre-object/src/typeobject.rs` around lines 807 - 820, Update
w_type_get_name_obj and w_type_get_qualname_obj so each lazy assignment to the
GC-tracked w_name or w_qualname field is immediately followed by
crate::gc_hook::try_gc_write_barrier(obj as *mut u8). Leave the existing caching
and return behavior unchanged.

Comment on lines +848 to 853
pub unsafe fn w_type_set_qualname(obj: PyObjectRef, w_qualname: PyObjectRef) {
let t = &mut *(obj as *mut W_TypeObject);
*t.qualname = crate::w_str_get_value(w_qualname).to_string();
t.w_qualname = w_qualname;
crate::gc_hook::try_gc_write_barrier(obj as *mut u8);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

__qualname__ can crash the interpreter on a lone-surrogate string; __name__'s surrogate guard was never mirrored for __qualname__. w_type_set_qualname stores the value's native form via w_str_get_value, which panics (.expect(...)) when the backing WTF-8 buffer holds an unpaired surrogate. Both places that call it validate only is_str(value), never surrogate-safety — unlike the __name__ setter, which explicitly runs check_surrogate first. CPython never crashes on this input (a __qualname__ str is stored as-is); this is a genuine interpreter-parity/crash defect, user-triggerable via class X: __qualname__ = "\udc80" or X.__qualname__ = "\udc80".

  • pyre/pyre-object/src/typeobject.rs#L848-L853: root-cause implementation — either add a surrogate guard here (mirroring check_surrogate) or document/enforce that all callers must pre-validate, then update both call sites below to match.
  • pyre/pyre-interpreter/src/builtins.rs#L3655-L3670 (type_new_take_qualname): call crate::builtins::check_surrogate(value)? before pyre_object::w_type_set_qualname(w_type, value).
  • pyre/pyre-interpreter/src/baseobjspace.rs#L8611-L8624 (object_setattr's __qualname__ branch): call check_surrogate(value)? before pyre_object::w_type_set_qualname(obj, value).
📍 Affects 3 files
  • pyre/pyre-object/src/typeobject.rs#L848-L853 (this comment)
  • pyre/pyre-interpreter/src/builtins.rs#L3655-L3670
  • pyre/pyre-interpreter/src/baseobjspace.rs#L8611-L8624
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pyre/pyre-object/src/typeobject.rs` around lines 848 - 853, Prevent
lone-surrogate __qualname__ values from reaching w_type_set_qualname by adding
check_surrogate validation in type_new_take_qualname at
pyre/pyre-interpreter/src/builtins.rs:3655-3670 and the __qualname__ branch of
object_setattr at pyre/pyre-interpreter/src/baseobjspace.rs:8611-8624, before
calling the setter. Update w_type_set_qualname in
pyre/pyre-object/src/typeobject.rs:848-853 only as needed to preserve this
contract, ensuring valid strings are stored unchanged and invalid values return
an error instead of panicking.

@youknowone

Copy link
Copy Markdown
Owner Author

Superseded by #726 after moving the complete stdlib work onto a fresh branch based on latest main in the primary /Users/youknowone/Projects/pyre worktree.

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.

1 participant