Skip to content

Implement a new OwnedOrReference memory utility - #2774

Merged
jviotti merged 2 commits into
mainfrom
maybe-owned
Aug 28, 2026
Merged

Implement a new OwnedOrReference memory utility#2774
jviotti merged 2 commits into
mainfrom
maybe-owned

Conversation

@jviotti

@jviotti jviotti commented Aug 28, 2026

Copy link
Copy Markdown
Member

Signed-off-by: Juan Cruz Viotti jv@jviotti.com

Review in cubic

Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
@jviotti

jviotti commented Aug 28, 2026

Copy link
Copy Markdown
Member Author

@cubic-ai review

@cubic-dev-ai

cubic-dev-ai Bot commented Aug 28, 2026

Copy link
Copy Markdown

@cubic-ai review

@jviotti I have started the AI code review. It will take a few minutes to complete.

@augmentcode

augmentcode Bot commented Aug 28, 2026

Copy link
Copy Markdown
🤖 Augment PR Summary

Summary: This PR introduces a new header-only memory language component.

Changes:

  • Adds OwnedOrReference<T>, which can hold an owned optional value or borrow a long-lived value.
  • Exposes value access, pointer/dereference operators, presence checks, and rvalue-only ownership extraction.
  • Adds the Ownable concept to constrain supported stored types.
  • Registers the component with the top-level build, installation/export configuration, and package component lookup.
  • Adds unit tests for empty, owned, referenced, move-only, move, and extraction behavior.
  • Extends the find-package integration fixture to link and include the new target.
  • Disables the new component in website-only build and deploy workflows.
Technical notes: Borrowed values are stored as const T*; callers are responsible for ensuring the referent remains stable and alive while it is read.

🤖 Was this summary useful? React with 👍 or 👎

@augmentcode augmentcode 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.

Review completed. 1 suggestion posted.

Fix All in Augment

Comment augment review to trigger a new review at any time.

OwnedOrReference(const OwnedOrReference &) = delete;
auto operator=(const OwnedOrReference &) -> OwnedOrReference & = delete;
OwnedOrReference(OwnedOrReference &&) = default;
auto operator=(OwnedOrReference &&) -> OwnedOrReference & = default;

@augmentcode augmentcode Bot Aug 28, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

At src/lang/memory/include/sourcemeta/core/memory_owned_or_reference.h:76, when the source borrows the target’s owned value (for example, OwnedOrReference<T> borrowed{target.value()}; target = std::move(borrowed);), memberwise assignment clears target.owned_ before copying borrowed.referenced_. The target then selects a dangling pointer in value(), so this publicly constructible aliasing case has use-after-free behavior.

Severity: medium

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

@github-actions github-actions 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.

Benchmark (linux/llvm)

Details
Benchmark suite Current: fd12d23 Previous: f69eafb Ratio
Regex_Lower_S_Or_Upper_S_Asterisk 2.188720581463846 ns/iter 2.4884130312074215 ns/iter 0.88
Regex_Caret_Lower_S_Or_Upper_S_Asterisk_Dollar 2.1782760005585886 ns/iter 2.460737034914427 ns/iter 0.89
Regex_Period_Asterisk 2.17804989725783 ns/iter 2.4625929653064644 ns/iter 0.88
Regex_Group_Period_Asterisk_Group 2.178384219290354 ns/iter 2.4712752292977918 ns/iter 0.88
Regex_Period_Plus 2.802491372379258 ns/iter 3.8712103067816184 ns/iter 0.72
Regex_Period 2.8082947431299576 ns/iter 3.8692310457620134 ns/iter 0.73
Regex_Caret_Period_Plus_Dollar 2.79977313409954 ns/iter 3.8698058203172074 ns/iter 0.72
Regex_Caret_Group_Period_Plus_Group_Dollar 2.8010876324473486 ns/iter 3.866428156068232 ns/iter 0.72
Regex_Caret_Period_Asterisk_Dollar 3.110215127134372 ns/iter 2.461708850079733 ns/iter 1.26
Regex_Caret_Group_Period_Asterisk_Group_Dollar 2.1783277766182225 ns/iter 2.461994536906273 ns/iter 0.88
Regex_Caret_X_Hyphen 5.297218027796066 ns/iter 6.746779777122211 ns/iter 0.79
Regex_Period_Md_Dollar 27.424842855123572 ns/iter 26.205919851653285 ns/iter 1.05
Regex_Caret_Slash_Period_Asterisk 5.710729906326224 ns/iter 7.314154268712151 ns/iter 0.78
Regex_Caret_Period_Range_Dollar 2.801924382899019 ns/iter 3.6380529256843332 ns/iter 0.77
Regex_Nested_Backtrack 38.40707620611925 ns/iter 38.65412722320275 ns/iter 0.99
JSON_Array_Of_Objects_Unique 451.1070202317697 ns/iter 476.2605599219049 ns/iter 0.95
JSON_Parse_1 4505.23305495694 ns/iter 4378.939459270909 ns/iter 1.03
JSON_Parse_Real 5185.969624424431 ns/iter 5023.327739999956 ns/iter 1.03
JSON_Parse_Decimal 7475.060462334318 ns/iter 7388.621687561396 ns/iter 1.01
JSON_Parse_Schema_ISO_Language 3241054.483870904 ns/iter 3307806.5377357583 ns/iter 0.98
JSON_Parse_Integer 3541.7450859415876 ns/iter 3747.316345590892 ns/iter 0.95
JSON_Parse_String_NonSSO_Plain 2969.49785282912 ns/iter 3093.85450953128 ns/iter 0.96
JSON_Parse_String_SSO_Plain 2577.427210164116 ns/iter 2633.696270463931 ns/iter 0.98
JSON_Parse_String_Escape_Heavy 12124.152865141165 ns/iter 12062.794008797977 ns/iter 1.01
JSON_Parse_Object_Short_Keys 7750.334976458156 ns/iter 7716.813713318759 ns/iter 1.00
JSON_Parse_Object_Scalar_Properties 4022.178292305564 ns/iter 3917.461406652149 ns/iter 1.03
JSON_Parse_Object_Array_Properties 5304.141707313329 ns/iter 5317.702621074854 ns/iter 1.00
JSON_Parse_Object_Object_Properties 5295.4346368123215 ns/iter 5295.701112853668 ns/iter 1.00
JSON_Parse_Nested_Containers 34619.9902666742 ns/iter 34008.77222845473 ns/iter 1.02
JSON_From_String_Copy 10.862049291088027 ns/iter 11.760441712578192 ns/iter 0.92
JSON_From_String_Temporary 9.917698633987236 ns/iter 10.064613855435997 ns/iter 0.99
JSON_Number_To_Double 23.402638528647874 ns/iter 22.846559833186742 ns/iter 1.02
JSON_Object_At_Last_Key/8 3.9193740793220617 ns/iter 4.029512740252286 ns/iter 0.97
JSON_Object_At_Last_Key/32 12.281156489871863 ns/iter 13.335027048719926 ns/iter 0.92
JSON_Object_At_Last_Key/128 49.138258375941476 ns/iter 46.83488685147448 ns/iter 1.05
JSON_Object_At_Last_Key/512 384.5437721418027 ns/iter 360.6595800037441 ns/iter 1.07
JSON_Fast_Hash_Helm_Chart_Lock 55.911476436331455 ns/iter 66.12162710762902 ns/iter 0.85
JSON_Equality_Helm_Chart_Lock 156.9181156746328 ns/iter 161.05492452145324 ns/iter 0.97
JSON_Divisible_By_Decimal 246.16199627916117 ns/iter 250.47835039205842 ns/iter 0.98
JSON_String_Equal/10 5.91835600222862 ns/iter 5.633446397930454 ns/iter 1.05
JSON_String_Equal/100 6.544436361776354 ns/iter 6.335018154004917 ns/iter 1.03
JSON_String_Equal_Small_By_Perfect_Hash/10 0.953269539545265 ns/iter 1.0556436630129387 ns/iter 0.90
JSON_String_Equal_Small_By_Runtime_Perfect_Hash/10 14.927955135216541 ns/iter 12.477760385894335 ns/iter 1.20
JSON_String_Fast_Hash/10 2.184816099856054 ns/iter 2.1110357489597704 ns/iter 1.03
JSON_String_Fast_Hash/100 2.1786280751211375 ns/iter 2.111072722836147 ns/iter 1.03
JSON_String_Key_Hash/10 2.7135977126496655 ns/iter 2.4618714271649655 ns/iter 1.10
JSON_String_Key_Hash/100 9.025084832961221 ns/iter 8.196151044277862 ns/iter 1.10
JSON_Object_Defines_Miss_Same_Length 3.4264375414669894 ns/iter 4.221022165413392 ns/iter 0.81
JSON_Object_Defines_Miss_Too_Small 3.1902669159432673 ns/iter 3.196846100610072 ns/iter 1.00
JSON_Object_Defines_Miss_Too_Large 2.7304964062442716 ns/iter 3.0781881212554207 ns/iter 0.89
Pointer_Object_Traverse 28.55522594274324 ns/iter 30.61094573134936 ns/iter 0.93
Pointer_Object_Try_Traverse 30.5598943417695 ns/iter 32.70211456747107 ns/iter 0.93
Pointer_Push_Back_Pointer_To_Weak_Pointer 200.60893153947208 ns/iter 180.8061425076066 ns/iter 1.11
Pointer_Walker_Schema_ISO_Language 1566263.1489841735 ns/iter 1575872.1770114673 ns/iter 0.99
Pointer_Maybe_Tracked_Deeply_Nested/0 1273657.0828829408 ns/iter 1266159.3224637492 ns/iter 1.01
Pointer_Maybe_Tracked_Deeply_Nested/1 1660589.6190476362 ns/iter 1914561.5107033886 ns/iter 0.87
Pointer_Position_Tracker_Get_Deeply_Nested 658.1851453730758 ns/iter 710.1000445950247 ns/iter 0.93
JSONPath_Descendant_Filter_Nested 1528.3548515609937 ns/iter 1525.7236538200914 ns/iter 1.00
URITemplateRouter_Create 25036.47643979025 ns/iter 22118.355261091856 ns/iter 1.13
URITemplateRouter_Match 177.106051549541 ns/iter 179.5416531243094 ns/iter 0.99
URITemplateRouter_Match_BasePath 200.93393989610442 ns/iter 212.73695340565342 ns/iter 0.94
URITemplateRouterView_Restore 8426.037285501885 ns/iter 9916.539042538572 ns/iter 0.85
URITemplateRouterView_Match 140.12951617208037 ns/iter 143.9400998095039 ns/iter 0.97
URITemplateRouterView_Match_BasePath 161.87076817401567 ns/iter 164.24651007833808 ns/iter 0.99
URITemplateRouterView_Arguments 423.266251058413 ns/iter 450.25182761029606 ns/iter 0.94
JSONL_Parse_Large 9402226.157894533 ns/iter 8612494.975609729 ns/iter 1.09
JSONL_Parse_Large_GZIP 10985613.23437508 ns/iter 10323870.470588425 ns/iter 1.06
JSONLD_Catalog_Annotation_List_Populate 613519.0215439904 ns/iter 589178.0302013519 ns/iter 1.04
JSONLD_Catalog_Materialize 3533586.8163263155 ns/iter 3554287.387755106 ns/iter 0.99
HTML_Build_Table_100000 58489985.18182085 ns/iter 67405181.69999917 ns/iter 0.87
HTML_Render_Table_100000 1971226.6397694487 ns/iter 2019103.4285713679 ns/iter 0.98
GZIP_Compress_ISO_Language_Set_3_Locations 34130978.8000018 ns/iter 35823532.20000129 ns/iter 0.95
GZIP_Decompress_ISO_Language_Set_3_Locations 4258347.083832577 ns/iter 4269583.530487938 ns/iter 1.00
GZIP_Compress_ISO_Language_Set_3_Schema 1925938.8928571003 ns/iter 2138147.1310974467 ns/iter 0.90
GZIP_Decompress_ISO_Language_Set_3_Schema 353028.96450306644 ns/iter 278110.8028560106 ns/iter 1.27
JOSE_VerifySignature_RS256 56846.26569105821 ns/iter 63939.62968036457 ns/iter 0.89
JOSE_VerifySignature_ES512 2466423.109154903 ns/iter 2659108.8212926774 ns/iter 0.93

This comment was automatically generated by workflow using github-action-benchmark.

@github-actions github-actions 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.

Benchmark (linux/gcc)

Details
Benchmark suite Current: fd12d23 Previous: f69eafb Ratio
JOSE_VerifySignature_RS256 21071.103041280923 ns/iter 22168.73600228386 ns/iter 0.95
JOSE_VerifySignature_ES512 466519.0885485975 ns/iter 575824.785655401 ns/iter 0.81
GZIP_Compress_ISO_Language_Set_3_Locations 26476786.55555473 ns/iter 36602686.21052715 ns/iter 0.72
GZIP_Decompress_ISO_Language_Set_3_Locations 3448309.256157665 ns/iter 4479699.645962619 ns/iter 0.77
GZIP_Compress_ISO_Language_Set_3_Schema 1707527.60396036 ns/iter 2045148.792397603 ns/iter 0.83
GZIP_Decompress_ISO_Language_Set_3_Schema 320745.0487693666 ns/iter 377041.39160840074 ns/iter 0.85
HTML_Build_Table_100000 51040909.090909794 ns/iter 56098712.81818228 ns/iter 0.91
HTML_Render_Table_100000 2824349.185185204 ns/iter 1864473.5848564103 ns/iter 1.51
JSONLD_Catalog_Annotation_List_Populate 656927.5982986961 ns/iter 682573.2987141616 ns/iter 0.96
JSONLD_Catalog_Materialize 2900416.8185653524 ns/iter 3895880.8814433347 ns/iter 0.74
JSONL_Parse_Large 8036881.399999963 ns/iter 10247471.985294128 ns/iter 0.78
JSONL_Parse_Large_GZIP 9471330.864865063 ns/iter 11492513.399999876 ns/iter 0.82
URITemplateRouter_Create 16140.247686369505 ns/iter 20735.42503178535 ns/iter 0.78
URITemplateRouter_Match 146.20191406133026 ns/iter 158.59236711435344 ns/iter 0.92
URITemplateRouter_Match_BasePath 167.63516755104374 ns/iter 185.39004185093162 ns/iter 0.90
URITemplateRouterView_Restore 3329.594115327161 ns/iter 8542.901270677374 ns/iter 0.39
URITemplateRouterView_Match 115.16411673383227 ns/iter 124.60717971098747 ns/iter 0.92
URITemplateRouterView_Match_BasePath 130.68642744194293 ns/iter 149.79254041069632 ns/iter 0.87
URITemplateRouterView_Arguments 429.24556741550117 ns/iter 472.20331860405497 ns/iter 0.91
JSONPath_Descendant_Filter_Nested 1245.1496741624896 ns/iter 1655.4100411068055 ns/iter 0.75
Pointer_Object_Traverse 22.88028188973464 ns/iter 24.955895090058895 ns/iter 0.92
Pointer_Object_Try_Traverse 22.238742489000455 ns/iter 23.073865397331247 ns/iter 0.96
Pointer_Push_Back_Pointer_To_Weak_Pointer 102.18576541462599 ns/iter 134.2793633854266 ns/iter 0.76
Pointer_Walker_Schema_ISO_Language 1746798.1721518852 ns/iter 1420500.0349076653 ns/iter 1.23
Pointer_Maybe_Tracked_Deeply_Nested/0 1067840.1951219689 ns/iter 1197967.135042718 ns/iter 0.89
Pointer_Maybe_Tracked_Deeply_Nested/1 1624954.1971831147 ns/iter 1709229.9583332944 ns/iter 0.95
Pointer_Position_Tracker_Get_Deeply_Nested 614.6787850057785 ns/iter 603.1558068275378 ns/iter 1.02
JSON_Array_Of_Objects_Unique 393.66460812023877 ns/iter 462.6222457403554 ns/iter 0.85
JSON_Parse_1 4386.3310466984685 ns/iter 5304.890191776696 ns/iter 0.83
JSON_Parse_Real 4877.672941660177 ns/iter 5763.412002758096 ns/iter 0.85
JSON_Parse_Decimal 7512.783164584031 ns/iter 10491.900496470254 ns/iter 0.72
JSON_Parse_Schema_ISO_Language 3195938.8571427315 ns/iter 3576844.4744899375 ns/iter 0.89
JSON_Parse_Integer 3070.6479342959374 ns/iter 3725.773345871975 ns/iter 0.82
JSON_Parse_String_NonSSO_Plain 2613.852538093994 ns/iter 3250.6351891068334 ns/iter 0.80
JSON_Parse_String_SSO_Plain 2476.0586464409425 ns/iter 3029.4476410461193 ns/iter 0.82
JSON_Parse_String_Escape_Heavy 15527.141986538034 ns/iter 16650.853609864756 ns/iter 0.93
JSON_Parse_Object_Short_Keys 7247.410212277495 ns/iter 8518.830630258033 ns/iter 0.85
JSON_Parse_Object_Scalar_Properties 3683.794423801606 ns/iter 4254.636795176433 ns/iter 0.87
JSON_Parse_Object_Array_Properties 5416.489344435986 ns/iter 6384.291846979531 ns/iter 0.85
JSON_Parse_Object_Object_Properties 5602.312909549145 ns/iter 6435.600922065288 ns/iter 0.87
JSON_Parse_Nested_Containers 35011.63379509627 ns/iter 39241.481976941024 ns/iter 0.89
JSON_From_String_Copy 7.953998823082765 ns/iter 8.541109917515547 ns/iter 0.93
JSON_From_String_Temporary 5.792509354437904 ns/iter 7.195135502522248 ns/iter 0.81
JSON_Number_To_Double 22.142605071907823 ns/iter 20.5931530914767 ns/iter 1.08
JSON_Object_At_Last_Key/8 5.054640270618098 ns/iter 3.740966817134817 ns/iter 1.35
JSON_Object_At_Last_Key/32 12.607684011529523 ns/iter 11.875825254297645 ns/iter 1.06
JSON_Object_At_Last_Key/128 47.84653641657133 ns/iter 48.61466721780844 ns/iter 0.98
JSON_Object_At_Last_Key/512 199.553682997506 ns/iter 358.6214680756582 ns/iter 0.56
JSON_Fast_Hash_Helm_Chart_Lock 69.06960047587579 ns/iter 72.90800160644454 ns/iter 0.95
JSON_Equality_Helm_Chart_Lock 126.14893616643806 ns/iter 159.35949733444755 ns/iter 0.79
JSON_Divisible_By_Decimal 236.97306271150833 ns/iter 258.5633901520767 ns/iter 0.92
JSON_String_Equal/10 5.063390647603061 ns/iter 5.6057604155002405 ns/iter 0.90
JSON_String_Equal/100 6.484986280752266 ns/iter 5.997799175596543 ns/iter 1.08
JSON_String_Equal_Small_By_Perfect_Hash/10 0.8638807095511225 ns/iter 0.7401395456929125 ns/iter 1.17
JSON_String_Equal_Small_By_Runtime_Perfect_Hash/10 15.860327883098943 ns/iter 25.193945834278477 ns/iter 0.63
JSON_String_Fast_Hash/10 3.030717693764483 ns/iter 3.1505706960083586 ns/iter 0.96
JSON_String_Fast_Hash/100 3.2218787818737864 ns/iter 3.1535313836592236 ns/iter 1.02
JSON_String_Key_Hash/10 1.8086852728366132 ns/iter 1.6187619382516643 ns/iter 1.12
JSON_String_Key_Hash/100 12.210869522851999 ns/iter 12.442259240722402 ns/iter 0.98
JSON_Object_Defines_Miss_Same_Length 2.843447339939471 ns/iter 3.4242507160808864 ns/iter 0.83
JSON_Object_Defines_Miss_Too_Small 3.100896576816061 ns/iter 3.1128754726283754 ns/iter 1.00
JSON_Object_Defines_Miss_Too_Large 2.835455490923495 ns/iter 3.4567758997792066 ns/iter 0.82
Regex_Lower_S_Or_Upper_S_Asterisk 0.9264159724782799 ns/iter 0.6232169906727918 ns/iter 1.49
Regex_Caret_Lower_S_Or_Upper_S_Asterisk_Dollar 0.9229827542268747 ns/iter 0.623374527852774 ns/iter 1.48
Regex_Period_Asterisk 0.9029950807190337 ns/iter 0.6255115084456976 ns/iter 1.44
Regex_Group_Period_Asterisk_Group 0.8892254210186152 ns/iter 0.6229714710461275 ns/iter 1.43
Regex_Period_Plus 0.8808295104291688 ns/iter 0.6228164155608633 ns/iter 1.41
Regex_Period 0.8920026080954232 ns/iter 0.6231607391036613 ns/iter 1.43
Regex_Caret_Period_Plus_Dollar 0.899131179048035 ns/iter 0.6236413821478847 ns/iter 1.44
Regex_Caret_Group_Period_Plus_Group_Dollar 0.9020337696973302 ns/iter 0.6231896545836457 ns/iter 1.45
Regex_Caret_Period_Asterisk_Dollar 0.9040450349496184 ns/iter 0.6228193654385223 ns/iter 1.45
Regex_Caret_Group_Period_Asterisk_Group_Dollar 0.9333082699554919 ns/iter 0.6225401001982364 ns/iter 1.50
Regex_Caret_X_Hyphen 2.8632564341079028 ns/iter 3.738022607170993 ns/iter 0.77
Regex_Period_Md_Dollar 16.00905710212351 ns/iter 28.140922140727955 ns/iter 0.57
Regex_Caret_Slash_Period_Asterisk 2.88812909484237 ns/iter 4.04484038140929 ns/iter 0.71
Regex_Caret_Period_Range_Dollar 1.5053512340977706 ns/iter 1.2457892720150332 ns/iter 1.21
Regex_Nested_Backtrack 33.26179130494241 ns/iter 37.43869455547715 ns/iter 0.89

This comment was automatically generated by workflow using github-action-benchmark.

@cubic-dev-ai cubic-dev-ai 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.

2 issues found across 11 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="src/lang/memory/include/sourcemeta/core/memory_owned_or_reference.h">

<violation number="1" location="src/lang/memory/include/sourcemeta/core/memory_owned_or_reference.h:79">
P1: When a borrowed `OwnedOrReference` points at the destination’s current `owned_` value, the defaulted move assignment destroys that value before copying the borrowed pointer, leaving `referenced_` dangling. Implement a custom move assignment that detects this aliasing case before replacing `owned_`.</violation>

<violation number="2" location="src/lang/memory/include/sourcemeta/core/memory_owned_or_reference.h:103">
P3: `to_owned() &&` is disabled for the move-only types that this type explicitly supports, so an owned move-only value can never be extracted even though the owned branch only needs a move. After construction, `Ownable` accepts any `std::move_constructible` object (and the tests target a `MoveOnly` type and a `holds_a_move_only_value` case), but calling `to_owned()` on such an `OwnedOrReference` fails to compile because the whole overload is gated on `std::copy_constructible<T>`. Only the referenced branch (`return *this->referenced_;`) actually needs copyability; the owned branch (`std::move(this->owned_).value()`) needs only a move. This contradicts the method's stated contract ("moving out of this one when it owns it"). Requiring copyability should be scoped to the referenced-copy path, not the whole function, so owned move-only values can be moved out.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

/// Move
OwnedOrReference(OwnedOrReference &&) = default;
/// Move
auto operator=(OwnedOrReference &&) -> OwnedOrReference & = default;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1: When a borrowed OwnedOrReference points at the destination’s current owned_ value, the defaulted move assignment destroys that value before copying the borrowed pointer, leaving referenced_ dangling. Implement a custom move assignment that detects this aliasing case before replacing owned_.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/lang/memory/include/sourcemeta/core/memory_owned_or_reference.h, line 79:

<comment>When a borrowed `OwnedOrReference` points at the destination’s current `owned_` value, the defaulted move assignment destroys that value before copying the borrowed pointer, leaving `referenced_` dangling. Implement a custom move assignment that detects this aliasing case before replacing `owned_`.</comment>

<file context>
@@ -0,0 +1,120 @@
+  /// Move
+  OwnedOrReference(OwnedOrReference &&) = default;
+  /// Move
+  auto operator=(OwnedOrReference &&) -> OwnedOrReference & = default;
+  ~OwnedOrReference() = default;
+
</file context>
Suggested change
auto operator=(OwnedOrReference &&) -> OwnedOrReference & = default;
auto operator=(OwnedOrReference &&other) -> OwnedOrReference & {
if (this == &other) {
return *this;
}
if (this->owned_.has_value() &&
other.referenced_ == &this->owned_.value()) {
return *this;
}
this->owned_ = std::move(other.owned_);
this->referenced_ = other.referenced_;
return *this;
}

Comment thread src/lang/memory/include/sourcemeta/core/memory_owned_or_reference.h Outdated
/// Get a value the caller owns, moving out of this one when it owns it and
/// copying only when it holds a reference
[[nodiscard]] auto to_owned() && -> T
requires std::copy_constructible<T>

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P3: to_owned() && is disabled for the move-only types that this type explicitly supports, so an owned move-only value can never be extracted even though the owned branch only needs a move. After construction, Ownable accepts any std::move_constructible object (and the tests target a MoveOnly type and a holds_a_move_only_value case), but calling to_owned() on such an OwnedOrReference fails to compile because the whole overload is gated on std::copy_constructible<T>. Only the referenced branch (return *this->referenced_;) actually needs copyability; the owned branch (std::move(this->owned_).value()) needs only a move. This contradicts the method's stated contract ("moving out of this one when it owns it"). Requiring copyability should be scoped to the referenced-copy path, not the whole function, so owned move-only values can be moved out.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/lang/memory/include/sourcemeta/core/memory_owned_or_reference.h, line 103:

<comment>`to_owned() &&` is disabled for the move-only types that this type explicitly supports, so an owned move-only value can never be extracted even though the owned branch only needs a move. After construction, `Ownable` accepts any `std::move_constructible` object (and the tests target a `MoveOnly` type and a `holds_a_move_only_value` case), but calling `to_owned()` on such an `OwnedOrReference` fails to compile because the whole overload is gated on `std::copy_constructible<T>`. Only the referenced branch (`return *this->referenced_;`) actually needs copyability; the owned branch (`std::move(this->owned_).value()`) needs only a move. This contradicts the method's stated contract ("moving out of this one when it owns it"). Requiring copyability should be scoped to the referenced-copy path, not the whole function, so owned move-only values can be moved out.</comment>

<file context>
@@ -0,0 +1,120 @@
+  /// Get a value the caller owns, moving out of this one when it owns it and
+  /// copying only when it holds a reference
+  [[nodiscard]] auto to_owned() && -> T
+    requires std::copy_constructible<T>
+  {
+    assert(this->has_value());
</file context>

@github-actions github-actions 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.

Benchmark (windows/msvc)

Details
Benchmark suite Current: fd12d23 Previous: f69eafb Ratio
Regex_Lower_S_Or_Upper_S_Asterisk 3.9210803571425905 ns/iter 5.024749999999958 ns/iter 0.78
Regex_Caret_Lower_S_Or_Upper_S_Asterisk_Dollar 3.8422451854326 ns/iter 5.039869999999951 ns/iter 0.76
Regex_Period_Asterisk 3.8433921359943346 ns/iter 5.104368000000363 ns/iter 0.75
Regex_Group_Period_Asterisk_Group 3.849516183035893 ns/iter 5.050395000000094 ns/iter 0.76
Regex_Period_Plus 3.590000886446534 ns/iter 4.901311050201313 ns/iter 0.73
Regex_Period 3.567796445317923 ns/iter 4.829895492149502 ns/iter 0.74
Regex_Caret_Period_Plus_Dollar 3.5673051283551205 ns/iter 4.774575892857363 ns/iter 0.75
Regex_Caret_Group_Period_Plus_Group_Dollar 3.5825806194025187 ns/iter 4.8221205357142445 ns/iter 0.74
Regex_Caret_Period_Asterisk_Dollar 3.841714285714686 ns/iter 5.048033035714233 ns/iter 0.76
Regex_Caret_Group_Period_Asterisk_Group_Dollar 3.8879212430571304 ns/iter 5.091234000000213 ns/iter 0.76
Regex_Caret_X_Hyphen 6.040900000000095 ns/iter 8.175871651785776 ns/iter 0.74
Regex_Period_Md_Dollar 41.27493514726769 ns/iter 47.24996087611785 ns/iter 0.87
Regex_Caret_Slash_Period_Asterisk 5.846497321428501 ns/iter 7.925393973214742 ns/iter 0.74
Regex_Caret_Period_Range_Dollar 4.1489110026121265 ns/iter 5.707647321428462 ns/iter 0.73
Regex_Nested_Backtrack 67.8650223214307 ns/iter 60.306741071432924 ns/iter 1.13
JSON_Array_Of_Objects_Unique 520.52249999997 ns/iter 617.7195535714069 ns/iter 0.84
JSON_Parse_1 7269.200892857494 ns/iter 8856.608258928565 ns/iter 0.82
JSON_Parse_Real 12800.46964285678 ns/iter 16285.88405725899 ns/iter 0.79
JSON_Parse_Decimal 8602.170758928043 ns/iter 11819.441071427913 ns/iter 0.73
JSON_Parse_Schema_ISO_Language 6224133.928572176 ns/iter 7581362.499999602 ns/iter 0.82
JSON_Parse_Integer 4618.730863590205 ns/iter 6532.235714285914 ns/iter 0.71
JSON_Parse_String_NonSSO_Plain 6234.216071428632 ns/iter 8463.765786759643 ns/iter 0.74
JSON_Parse_String_SSO_Plain 2860.6355682412714 ns/iter 3941.759486606942 ns/iter 0.73
JSON_Parse_String_Escape_Heavy 16764.519851693414 ns/iter 21877.921428570957 ns/iter 0.77
JSON_Parse_Object_Short_Keys 10081.59374999984 ns/iter 13252.89284422798 ns/iter 0.76
JSON_Parse_Object_Scalar_Properties 5310.4589285715465 ns/iter 6884.277678571391 ns/iter 0.77
JSON_Parse_Object_Array_Properties 9425.332476194255 ns/iter 11566.26071428641 ns/iter 0.81
JSON_Parse_Object_Object_Properties 9201.818741880465 ns/iter 11791.764062500042 ns/iter 0.78
JSON_Parse_Nested_Containers 64742.16964285517 ns/iter 85035.596625149 ns/iter 0.76
JSON_From_String_Copy 49.49065000000701 ns/iter 65.88318749999797 ns/iter 0.75
JSON_From_String_Temporary 63.093044642863156 ns/iter 57.920276785716446 ns/iter 1.09
JSON_Number_To_Double 104.7771874999981 ns/iter 121.2326071428598 ns/iter 0.86
JSON_Object_At_Last_Key/8 5.724864285714456 ns/iter 7.5677330019297715 ns/iter 0.76
JSON_Object_At_Last_Key/32 21.206244480440766 ns/iter 23.22128545512 ns/iter 0.91
JSON_Object_At_Last_Key/128 72.10700892856485 ns/iter 89.30167904902942 ns/iter 0.81
JSON_Object_At_Last_Key/512 333.1273176761385 ns/iter 426.32759563155287 ns/iter 0.78
JSON_Fast_Hash_Helm_Chart_Lock 86.37854078667735 ns/iter 104.13150000000648 ns/iter 0.83
JSON_Equality_Helm_Chart_Lock 158.34216517855992 ns/iter 208.96988352812616 ns/iter 0.76
JSON_Divisible_By_Decimal 309.22531250001026 ns/iter 306.5139285714074 ns/iter 1.01
JSON_String_Equal/10 7.688246651786912 ns/iter 10.522024506598724 ns/iter 0.73
JSON_String_Equal/100 8.788367187499343 ns/iter 11.69776428571469 ns/iter 0.75
JSON_String_Equal_Small_By_Perfect_Hash/10 1.6640739936784816 ns/iter 2.5134799999999506 ns/iter 0.66
JSON_String_Equal_Small_By_Runtime_Perfect_Hash/10 12.935489285713484 ns/iter 15.17211354833869 ns/iter 0.85
JSON_String_Fast_Hash/10 5.055174999999963 ns/iter 6.588872321428495 ns/iter 0.77
JSON_String_Fast_Hash/100 5.052106000000549 ns/iter 6.760481249999982 ns/iter 0.75
JSON_String_Key_Hash/10 3.8880223214286604 ns/iter 5.466966964285344 ns/iter 0.71
JSON_String_Key_Hash/100 8.495994604928846 ns/iter 11.919400000000024 ns/iter 0.71
JSON_Object_Defines_Miss_Same_Length 3.641963744308988 ns/iter 4.732809385564335 ns/iter 0.77
JSON_Object_Defines_Miss_Too_Small 3.5885585658211316 ns/iter 4.716897724267261 ns/iter 0.76
JSON_Object_Defines_Miss_Too_Large 3.5935395033132633 ns/iter 4.756082153473515 ns/iter 0.76
Pointer_Object_Traverse 52.033269999992626 ns/iter 68.41795758928245 ns/iter 0.76
Pointer_Object_Try_Traverse 52.85595999999941 ns/iter 71.22494419642729 ns/iter 0.74
Pointer_Push_Back_Pointer_To_Weak_Pointer 124.72726785714728 ns/iter 163.03528323897902 ns/iter 0.77
Pointer_Walker_Schema_ISO_Language 8904001.333333628 ns/iter 11125637.500000047 ns/iter 0.80
Pointer_Maybe_Tracked_Deeply_Nested/0 1872404.2895443523 ns/iter 2436154.062499973 ns/iter 0.77
Pointer_Maybe_Tracked_Deeply_Nested/1 2861764.6586344633 ns/iter 3835913.9037431017 ns/iter 0.75
Pointer_Position_Tracker_Get_Deeply_Nested 482.3010714285861 ns/iter 556.1126449475712 ns/iter 0.87
JSONPath_Descendant_Filter_Nested 2000.9393090841465 ns/iter 2401.606136600345 ns/iter 0.83
URITemplateRouter_Create 30054.022647271064 ns/iter 40652.521618013125 ns/iter 0.74
URITemplateRouter_Match 182.34583363922837 ns/iter 233.0949516635023 ns/iter 0.78
URITemplateRouter_Match_BasePath 205.13334867262415 ns/iter 268.1218490233 ns/iter 0.77
URITemplateRouterView_Restore 20674.18369806665 ns/iter 34701.52229424505 ns/iter 0.60
URITemplateRouterView_Match 140.16452722478883 ns/iter 187.22097012639594 ns/iter 0.75
URITemplateRouterView_Match_BasePath 157.66885430817402 ns/iter 209.41973298389678 ns/iter 0.75
URITemplateRouterView_Arguments 467.8917562258587 ns/iter 545.6003571428677 ns/iter 0.86
JSONL_Parse_Large 25685260.71428729 ns/iter 32825690.00000137 ns/iter 0.78
JSONL_Parse_Large_GZIP 27527123.076923158 ns/iter 33705300.00000014 ns/iter 0.82
JSONLD_Catalog_Annotation_List_Populate 2639146.785714226 ns/iter 3199604.4642857513 ns/iter 0.82
JSONLD_Catalog_Materialize 6918263.333333622 ns/iter 9994486.666666945 ns/iter 0.69
HTML_Build_Table_100000 75006128.57143097 ns/iter 92506033.3333363 ns/iter 0.81
HTML_Render_Table_100000 6815714.44444368 ns/iter 7905402.222221862 ns/iter 0.86
GZIP_Compress_ISO_Language_Set_3_Locations 29958700.000001956 ns/iter 35828585.000001565 ns/iter 0.84
GZIP_Decompress_ISO_Language_Set_3_Locations 7515069.999999469 ns/iter 10095424.44444441 ns/iter 0.74
GZIP_Compress_ISO_Language_Set_3_Schema 1764776.5217391325 ns/iter 2095171.3043478262 ns/iter 0.84
GZIP_Decompress_ISO_Language_Set_3_Schema 411038.5602678386 ns/iter 649494.5535714233 ns/iter 0.63
JOSE_VerifySignature_RS256 18434.63155920946 ns/iter 25305.96889327253 ns/iter 0.73
JOSE_VerifySignature_ES512 1227829.910714208 ns/iter 1415023.6401673697 ns/iter 0.87

This comment was automatically generated by workflow using github-action-benchmark.

@github-actions github-actions 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.

Benchmark (macos/llvm)

Details
Benchmark suite Current: fd12d23 Previous: f69eafb Ratio
Regex_Lower_S_Or_Upper_S_Asterisk 2.3867209133283755 ns/iter 2.0456059220173115 ns/iter 1.17
Regex_Caret_Lower_S_Or_Upper_S_Asterisk_Dollar 2.6431290066665074 ns/iter 2.0452476315346453 ns/iter 1.29
Regex_Period_Asterisk 2.5568264291035496 ns/iter 2.5009608730568424 ns/iter 1.02
Regex_Group_Period_Asterisk_Group 2.864939910512583 ns/iter 2.179354415634096 ns/iter 1.31
Regex_Period_Plus 2.9096944256060455 ns/iter 2.28771534496926 ns/iter 1.27
Regex_Period 2.799722848420279 ns/iter 2.6628584310689933 ns/iter 1.05
Regex_Caret_Period_Plus_Dollar 3.0114965006738363 ns/iter 2.4054926925145868 ns/iter 1.25
Regex_Caret_Group_Period_Plus_Group_Dollar 2.946371440027684 ns/iter 2.395518440595729 ns/iter 1.23
Regex_Caret_Period_Asterisk_Dollar 2.131975493600361 ns/iter 1.8347259164275478 ns/iter 1.16
Regex_Caret_Group_Period_Asterisk_Group_Dollar 2.083278085136973 ns/iter 1.797178047813772 ns/iter 1.16
Regex_Caret_X_Hyphen 8.405205856979125 ns/iter 6.740246688050831 ns/iter 1.25
Regex_Period_Md_Dollar 26.77673413796163 ns/iter 20.464533922868473 ns/iter 1.31
Regex_Caret_Slash_Period_Asterisk 5.596119757038301 ns/iter 5.132361751572248 ns/iter 1.09
Regex_Caret_Period_Range_Dollar 2.4546618012948342 ns/iter 2.7354036856988047 ns/iter 0.90
Regex_Nested_Backtrack 35.068877923416416 ns/iter 32.57294213884443 ns/iter 1.08
JSON_Array_Of_Objects_Unique 431.28069954533055 ns/iter 473.2361072633566 ns/iter 0.91
JSON_Parse_1 3728.717513798881 ns/iter 3252.4578060595795 ns/iter 1.15
JSON_Parse_Real 6682.108750730934 ns/iter 5861.0113280632 ns/iter 1.14
JSON_Parse_Decimal 6924.699839959067 ns/iter 5992.693714606234 ns/iter 1.16
JSON_Parse_Schema_ISO_Language 2636325.5813952344 ns/iter 2256450.6201297487 ns/iter 1.17
JSON_Parse_Integer 3893.538503593381 ns/iter 3953.051638555308 ns/iter 0.98
JSON_Parse_String_NonSSO_Plain 4244.786364957911 ns/iter 3221.6134049948196 ns/iter 1.32
JSON_Parse_String_SSO_Plain 2009.2190146736993 ns/iter 1876.0166265419778 ns/iter 1.07
JSON_Parse_String_Escape_Heavy 18421.10830231201 ns/iter 16712.046981131967 ns/iter 1.10
JSON_Parse_Object_Short_Keys 6441.718509145454 ns/iter 5934.6966207394435 ns/iter 1.09
JSON_Parse_Object_Scalar_Properties 3741.7173378942575 ns/iter 3217.207853609046 ns/iter 1.16
JSON_Parse_Object_Array_Properties 4525.1871176784225 ns/iter 4470.884732619589 ns/iter 1.01
JSON_Parse_Object_Object_Properties 5947.423847280208 ns/iter 4482.062750574556 ns/iter 1.33
JSON_Parse_Nested_Containers 34943.0866912615 ns/iter 27725.897877057803 ns/iter 1.26
JSON_From_String_Copy 15.377269155974682 ns/iter 11.34249831127692 ns/iter 1.36
JSON_From_String_Temporary 8.842302466466426 ns/iter 6.380137518947387 ns/iter 1.39
JSON_Number_To_Double 46.45669392202549 ns/iter 32.91845115838117 ns/iter 1.41
JSON_Object_At_Last_Key/8 5.8343627798247 ns/iter 4.489450462725714 ns/iter 1.30
JSON_Object_At_Last_Key/32 16.701991931891214 ns/iter 12.3718377885963 ns/iter 1.35
JSON_Object_At_Last_Key/128 69.53502297475747 ns/iter 51.4765087456422 ns/iter 1.35
JSON_Object_At_Last_Key/512 256.7698626904572 ns/iter 194.3015503399055 ns/iter 1.32
JSON_Fast_Hash_Helm_Chart_Lock 80.85902234235792 ns/iter 57.776354252998395 ns/iter 1.40
JSON_Equality_Helm_Chart_Lock 200.9917505797505 ns/iter 254.65917104092426 ns/iter 0.79
JSON_Divisible_By_Decimal 216.94006239919634 ns/iter 238.37574860440841 ns/iter 0.91
JSON_String_Equal/10 8.851035335151444 ns/iter 7.277372572351919 ns/iter 1.22
JSON_String_Equal/100 8.684726288942505 ns/iter 7.235708582365523 ns/iter 1.20
JSON_String_Equal_Small_By_Perfect_Hash/10 0.4522976185381608 ns/iter 0.34914362123138704 ns/iter 1.30
JSON_String_Equal_Small_By_Runtime_Perfect_Hash/10 4.19291462926328 ns/iter 3.456199510526342 ns/iter 1.21
JSON_String_Fast_Hash/10 2.9210535932591113 ns/iter 2.529583127198354 ns/iter 1.15
JSON_String_Fast_Hash/100 2.6141902030697493 ns/iter 2.127181778849073 ns/iter 1.23
JSON_String_Key_Hash/10 2.1040018033418355 ns/iter 1.7098583089768613 ns/iter 1.23
JSON_String_Key_Hash/100 3.4159161400993403 ns/iter 2.163355336516792 ns/iter 1.58
JSON_Object_Defines_Miss_Same_Length 3.3878134604943138 ns/iter 2.7882342716737547 ns/iter 1.22
JSON_Object_Defines_Miss_Too_Small 3.396112082369174 ns/iter 2.8069571742445962 ns/iter 1.21
JSON_Object_Defines_Miss_Too_Large 3.528461075870622 ns/iter 3.2421338610692754 ns/iter 1.09
Pointer_Object_Traverse 34.1498766929562 ns/iter 22.05794298697649 ns/iter 1.55
Pointer_Object_Try_Traverse 54.63189278710827 ns/iter 35.18567376680917 ns/iter 1.55
Pointer_Push_Back_Pointer_To_Weak_Pointer 224.1155437428089 ns/iter 153.80970494151993 ns/iter 1.46
Pointer_Walker_Schema_ISO_Language 2656932.84927528 ns/iter 1557602.0114942812 ns/iter 1.71
Pointer_Maybe_Tracked_Deeply_Nested/0 1422971.7874793322 ns/iter 965430.0430504214 ns/iter 1.47
Pointer_Maybe_Tracked_Deeply_Nested/1 1988653.8396944688 ns/iter 1795878.211469525 ns/iter 1.11
Pointer_Position_Tracker_Get_Deeply_Nested 579.5936785740672 ns/iter 424.78145550398057 ns/iter 1.36
JSONPath_Descendant_Filter_Nested 1831.1436469823157 ns/iter 1921.6447521746002 ns/iter 0.95
URITemplateRouter_Create 29005.75357253876 ns/iter 22042.533917952325 ns/iter 1.32
URITemplateRouter_Match 251.67239226069677 ns/iter 188.09924584739997 ns/iter 1.34
URITemplateRouter_Match_BasePath 301.8739663992706 ns/iter 241.87277313778387 ns/iter 1.25
URITemplateRouterView_Restore 15648.950223357642 ns/iter 15308.733682657947 ns/iter 1.02
URITemplateRouterView_Match 186.40638090000138 ns/iter 152.3092037331676 ns/iter 1.22
URITemplateRouterView_Match_BasePath 258.2211872264604 ns/iter 181.38108522503865 ns/iter 1.42
URITemplateRouterView_Arguments 837.2820122445922 ns/iter 631.9120423299361 ns/iter 1.32
JSONL_Parse_Large 11785412.573770327 ns/iter 7573868.46078357 ns/iter 1.56
JSONL_Parse_Large_GZIP 12643840.957746083 ns/iter 8604866.296702942 ns/iter 1.47
JSONLD_Catalog_Annotation_List_Populate 814429.0849673674 ns/iter 628961.3911290403 ns/iter 1.29
JSONLD_Catalog_Materialize 4307095.938271585 ns/iter 2604757.206766945 ns/iter 1.65
HTML_Build_Table_100000 80309515.62498955 ns/iter 46520212.94444669 ns/iter 1.73
HTML_Render_Table_100000 2814177.7777780895 ns/iter 1968056.233933384 ns/iter 1.43
GZIP_Compress_ISO_Language_Set_3_Locations 49180431.500003256 ns/iter 51184684.52381075 ns/iter 0.96
GZIP_Decompress_ISO_Language_Set_3_Locations 6227147.500000001 ns/iter 5533016.6086963 ns/iter 1.13
GZIP_Compress_ISO_Language_Set_3_Schema 2889674.3093525446 ns/iter 2445990.5495206793 ns/iter 1.18
GZIP_Decompress_ISO_Language_Set_3_Schema 406554.65032254905 ns/iter 427601.2968299644 ns/iter 0.95
JOSE_VerifySignature_RS256 33653.06799354356 ns/iter 34387.39399869405 ns/iter 0.98
JOSE_VerifySignature_ES512 1686115.5133928005 ns/iter 1256533.405286506 ns/iter 1.34

This comment was automatically generated by workflow using github-action-benchmark.

Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
@jviotti
jviotti merged commit 5e99d8d into main Aug 28, 2026
13 checks passed
@jviotti
jviotti deleted the maybe-owned branch August 28, 2026 14:39
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