Repository navigation
fix(evaluator): a write into a &T parameter's value is E0908 (S2); a nested comptime_expect_error keeps the outer one's mode - #1436
Merged
Conversation
shd101wyy
added a commit
that referenced
this pull request
Oct 17, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
shd101wyy
added a commit
that referenced
this pull request
Oct 17, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
shd101wyy
added a commit
that referenced
this pull request
Oct 17, 2026
… E0908; rc.test's fwb_scratch writes an owned copy Review of #1436: the shared-param and borrowed-copy E0908 entries were judged only when the callee was a FuncVal; an unknown mask now counts as a write. tests/rc.test.yo wrote a plain field through a &T parameter. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
shd101wyy
force-pushed
the
fix/field-write-through-shared-borrow
branch
from
October 17, 2026 16:39
4840824 to
4837a85
Compare
shd101wyy
added a commit
that referenced
this pull request
Oct 17, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
shd101wyy
added a commit
that referenced
this pull request
Oct 17, 2026
… E0908; rc.test's fwb_scratch writes an owned copy Review of #1436: the shared-param and borrowed-copy E0908 entries were judged only when the callee was a FuncVal; an unknown mask now counts as a write. tests/rc.test.yo wrote a plain field through a &T parameter. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
shd101wyy
force-pushed
the
fix/field-write-through-shared-borrow
branch
from
October 17, 2026 20:53
958fed2 to
2ea8c79
Compare
shd101wyy
added a commit
that referenced
this pull request
Oct 18, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
shd101wyy
added a commit
that referenced
this pull request
Oct 18, 2026
… E0908; rc.test's fwb_scratch writes an owned copy Review of #1436: the shared-param and borrowed-copy E0908 entries were judged only when the callee was a FuncVal; an unknown mask now counts as a write. tests/rc.test.yo wrote a plain field through a &T parameter. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
shd101wyy
force-pushed
the
fix/field-write-through-shared-borrow
branch
from
October 18, 2026 00:50
7ba9a05 to
7fc559d
Compare
…als rule yo fix --migrate mut-bindings (tree binary) on this branch's changed test files: 2 marks (fwb_scratch's owned copy; the x lent &mut to _through_mut). 4 parameter writes listed for hand rebinding follow in the next commit.
The migration lists the four writes of the by-value parameter p (its fields, element and &mut self receiver): a parameter takes no mut, so the body rebinds it (mut(q) := p) and writes the owned copy, as tests/mut_bindings.test.yo teaches.
shd101wyy
force-pushed
the
fix/field-write-through-shared-borrow
branch
from
October 18, 2026 12:54
7fc559d to
866182c
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes the S2 soundness hole
issues/fixed/a-field-write-through-a-shared-borrow-parameter-is-accepted-and-lost.md. Before this change,p.n = von ap : &Tparameter compiled and wrote only the callee's by-value copy, so the caller never saw the write. Every write into a&Tparameter's value is now E0908 (decision 42:x : &Tis read-only). The existing code for a write through a borrow is reused.shared_borrow_param_root_of_place(src/evaluator/exprs/assignment.yo) walks a place back to its root, but only through steps that stay inside the borrowed value: a value-struct or tuple field, a fixed-array element, a uniqueBoxpayload. If the root is anis_imm_borrowparameter (afn, a method'sself : &Self, or a closure), the place is inside that parameter's value. Three write sites consult it:p.n = v,p.inner.m = v,p.arr(i) = v,p.pair.0 = v,a(i) = v,b.n = vthroughb : &Box(P), andself.n = vin aself : &Selfmethod. A write whose old value holds RC data keeps its existing borrowed-copy message.&mutparameter or aself : &mut Selfreceiver the callee writes. Coversp.inc(),p.inner.bump(),f(&mut p.inner),g(&mut p.n, v),g(&mut p.inner.m, v),g(&mut p.arr(i), v)andg(&mut n, v)onn : &i32. These go through the existing D3 pending entries, which are judged against the callee's mutation mask.&mutlocal borrow of such a place (q := &mut p.inner.m).Scoped on purpose: handles are exempt. A step through a handle (a
refobject, anRc, a std collection) reaches storage the handle shares with the caller, so it stays legal. Lending a handle place to a&mutreceiver also stays legal:h.xs.push(v)onh : &H,em.emit(...)onem : &Emitter. The&mutargument check therefore applies only when the lent place's type holds no RC data. A value aggregate that holds RC data already gets the borrowed-copy E0908.The task said to fix any std/src sites the rule rejects. I scoped the rule instead, because
plans/VALUES_BY_DEFAULT.mdkeeps handle writes legal until the V2b flip. The unscoped version rejected 66 sites insrc/(check ./src: 69 files failed). Almost all wereem/emitter : &Emitterreceivers, plusfiles,registry, andsaved_names : &ArrayList(String)insrc/verifier/vc.yo:2491. Every one is a handle whose writes the caller does see.check ./stdwas clean under both versions.Two more bugs turned up while writing the test. Both are fixed here, each with a test that fails on develop:
issues/fixed/2026-10-17-comptime-expect-error-nested-in-another-resets-its-propagate-mode.md(S3). The element placey.arr(i)looksarrup as a method, which forces the type's impls. An impl member that holds its owncomptime_expect_errorthen ran inside the outer one's argument. On exit it reset the global propagate mode tofalseand cleared the observations, socheckre-raised the outer, expected error.evaluate_comptime_expect_errornow saves the propagate mode, the observed flag and the messages, and restores them on exit.issues/fixed/2026-10-17-e0908-prints-an-element-place-with-unbalanced-parentheses.md(S3). An E0908 named`y.arr)(usize(0)`._place_source_textnow useslocal_borrow_place_text, which strips only a pair of parentheses that encloses the whole text.A third bug was filed but is not fixed here:
issues/2026-10-17-a-fixed-array-literal-of-runtime-strings-emits-invalid-c.md(S2).[String.from("a"), String.from("b")]as a[String ; 2]emits/* skip generating value */inside a C initializer. It fails on develop too, and it is outside this change.The E0908 explanation (
yo explain E0908, en + zh-CN) no longer says that plain-data fields of a&Tparameter can be written, and it names the handle exemption. The handover,plans/VALUES_BY_DEFAULT.mdandplans/OWNERSHIP_AND_BORROWING_DOC_DRAFT.mdnow cite the fixed doc.Verification
Tree-built compiler at the rebased head (
2f5301589, on develop4d7c15caa; develop has since moved with src drift in files this branch does not touch (#1416, #1427), and a trial merge is clean),yo build --std-path ./std:yo check ./src --std-path ./std: 278/278 files passedyo check ./std --std-path ./std: 172/172 files passedtests/shared_borrow_write.test.yo5/5,tests/deref_auto.test.yo22/22tests/internal/assignment.test.yo9/9,initialization_assignment.test.yo4/4,diagnostics_registry.test.yo9/9,diagnostics_registry_examples.test.yo1/1 (run withYO_TEST_LEAK_VERDICT=0as CI runstests/internal; without it the batch fails only on the documented in-process evaluator-registry leak verdict, with no assertion failure)comptime_expect_errorusers, on the pre-rebase build (same branch diff, before develop's Async Mutex follows Rust: move-only, shared as Arc(Mutex(T)); E0909 accepts & through Arc; D3 checks every hop; with_lock no longer holds the guard (S2) #1380/fix(evaluator): D3 judges every callee by its mutation mask, not by its file (S1, B1 of #1380) #1397 src drift):parameter_modes43,local_borrows16,ref_local_binding16,move_only55,closure_capture_list41,for_macro_borrow27,index76,string/string302,async/sm_ownership45,async_await281,type_soundness71,basic57,comptime47,expected_error_keeps_prelude_env_clean1,safe_code_structural_gates1. All passed.build-stamp-dotted-dir,init*,skills-install*) were GOLDEN-DIFF only because the copied gate binary sat outside the tree and could not find.github/skills. They were re-run with the in-tree binary: PASS 7/7. No goldens were recorded.yo fmt --checkwith the tree binary on every changed.yofile;bash scripts/check-issue-refs.shpasses.1a4cf8df6binary),tests/shared_borrow_write.test.yofailsyo checkat its first case (p.n = i32(1)compiles). The nested-comptime_expect_errorand element-text cases fail on develop as described in their issue docs.docs/: no change needed. The user docs already say&Tis read-only, and none of them said plain fields could be written.LLM attribution
Deferred
&Tstay legal until the V2b flip makes the collections values. This includessrc/verifier/vc.yo:2491, which passes a bare&ArrayList(String)to a&mutparameter. A callee that reassigns the whole handle loses that write, which is the same family as this bug. There is also an asymmetry:g(&mut h.xs)is accepted whileq := &mut h.xsis E0908.issues/2026-10-17-a-fixed-array-literal-of-runtime-strings-emits-invalid-c.md(S2) is open. The suspected one-line fix inevaluate_array_valuemirrors the tuple literal's.yo test ./std, the fixpoint and the fulltests/internalare left to develop's battery (Tier 2/3).🤖 Generated with Claude Code