[1.0 Decision] Color/Vector copy semantics: value types vs write-through proxies #326
Labels
No labels
Alpha Release Requirement
Bugfix
Demo Target
Documentation
Major Feature
Minor Feature
priority:tier1-active
priority:tier2-foundation
priority:tier3-future
priority:tier4-deferred
Refactoring & Cleanup
system:animation
system:documentation
system:grid
system:input
system:performance
system:procgen
system:python-binding
system:rendering
system:ui-hierarchy
Tiny Feature
workflow:blocked
workflow:needs-benchmark
workflow:needs-documentation
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
john/McRogueFace#326
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
From the 2026-07-02 pre-1.0 memory-model review. This is a semantic decision that freezes at 1.0 — it cannot be changed compatibly afterward.
Current behavior
PyColorObjectandPyVectorObjectstore their data by value (sf::Color/sf::Vector2finline, noshared_ptr, no weakreflist —src/PyColor.h:8-11,src/PyVector.h:6-9). Every property getter returns a fresh copy:frame.fill_color→PyColor(color).pyObject()allocates a new object per read (src/UIFrame.cpp:346-371)frame.fill_color.r = 255is a silent no-op — you mutate a copy. The PyColor docstring already warns about this (src/PyColor.h:63-77).Unlike Frame/Caption/Sprite/Grid/Entity (which get identity preservation via
PythonObjectCache), Color/Vector have no serial number and are never cached.The decision
sf::Colorworks in C++. The.r = 255no-op footgun stays; mitigate with documentation and possibly a runtime warning on mutating an orphaned color.frame.fill_color is frame.fill_color) and must land before 1.0.Either answer is fine; not deciding is the only wrong option.
Related
PythonObjectCacheidentity mechanism:src/PythonObjectCache.h.posgetter is also pathologically slow (#331).DECIDED 2026-07-02: Option 1 — value semantics, forever.
Color/Vector remain plain value copies at every property boundary.
frame.fill_color.r = 255mutating a throwaway copy is the documented, frozen behavior; the supported idioms are read-modify-writeback (c = frame.fill_color; c.r = 255; frame.fill_color = c) or whole-value assignment (frame.fill_color = mcrfpy.Color(...)).Rationale: zero pre-1.0 implementation risk, matches sf::Color and the existing PyColor docstring warning, and avoids the dangling-parent lifetime / identity questions write-through proxies would freeze into the contract.
Follow-through (docs pass, will close this issue): make the copy-semantics statement explicit and normative in the PyColor/PyVector class docstrings (MCRF macros), the API reference intro, and the 1.0 compatibility policy alongside #327/#330.