Skip to content

The fifth convention: whether a call changes what it is called on - #162

Merged
matt-edmondson merged 1 commit into
mainfrom
claude/peaceful-mayer-oo6l2u
Sep 11, 2026
Merged

The fifth convention: whether a call changes what it is called on#162
matt-edmondson merged 1 commit into
mainfrom
claude/peaceful-mayer-oo6l2u

Conversation

@matt-edmondson

Copy link
Copy Markdown
Contributor

The four conventions say whether a call can fail, whether the callee may keep an argument, who frees what, and whether an argument is read-only. They say nothing about the receiver — so a schema could describe an interface whose every method might change the world, and a generator had no way to say otherwise.

The C++ target document's §3 writes find() as const, and #160's bridge could not emit it. A test asserted that gap rather than leaving it merely absent. This closes it.

SchemaFunction.IsQuery

{ "returnType": { "TypeName": "Optional", "elementType": { "TypeName": "Object", "className": "RigidBody" } }, "isQuery": true, "name": "Find" }

A query answers; a command acts.

Held per function rather than globally, unlike the other four. Those are rules the program keeps, which is what makes holding them globally the thing that stops annotation creep. This genuinely differs from one signature to the next, because it is a property of what the call does.

False by default and omitted from the file when it is, so every function a schema already declares goes on generating exactly as it did.

A query that answers nothing

A query returning Void changes nothing and answers nothing, so calling it cannot be observed at all.

Reported as a warning rather than an error: it is as often a signature someone is part way through writing as one they meant — the return type is usually the half that is missing. Result<Void> is exempt, because it answers whether the call succeeded, which is something.

The bridge

Schema.Cpp emits it as the trailing const, which is what lets a caller holding a const reference call it at all:

[[nodiscard]] virtual std::optional<RigidBody> find(EntityId entity) const = 0;

§3's acceptance test now asserts the document's text including that const, and AQueryCannotYetSayItLeavesTheReceiverUnchanged is replaced by AQuerySaysItLeavesTheReceiverUnchanged — which also checks a command does not claim it, since a rule that only ever says yes is not a rule. The suite records that the gap closed rather than quietly losing the note that it ever existed.

Format version

formatVersion moves to 6. Additive and omitted when false, but a version 5 reader would drop it and generate a signature that promises less than the schema does.

Testing

403 in Schema.Test (6 new in QueryFunctionTests), 46 in Schema.Cpp.Test, 201 in SchemaEditor.Test. Whole solution builds with 0 warnings.

🤖 Generated with Claude Code

https://claude.ai/code/session_01AhoPJ5AbxP8QEBNxPQYEPk


Generated by Claude Code

…d on

The four conventions say whether a call can fail, whether the callee may keep an
argument, who frees what, and whether an argument is read-only. They say nothing
about the receiver, so a schema could describe an interface whose every method
might change the world and a generator had no way to say otherwise. The C++
target document's own §3 wrote find() as const and the bridge could not emit it;
a test asserted that gap rather than leaving it merely absent, and this closes it.

SchemaFunction.IsQuery says a query answers and a command acts. Held per function
rather than globally, because unlike the other four this genuinely differs from
one signature to the next - it is a property of what the call does rather than a
rule the program keeps. False by default and omitted from the file when it is, so
every function a schema already declares goes on generating exactly as it did.

A query that returns Void changes nothing and answers nothing, so calling it
cannot be observed at all. Reported as a warning rather than an error, because it
is as often a signature someone is part way through writing as one they meant -
the return type is usually the half that is missing. Result<Void> is exempt: it
answers whether the call succeeded, which is something.

The bridge emits it as the trailing const, which is what lets a caller holding a
const reference call it. §3's acceptance test now asserts the document's text
including that const, and the test that asserted the gap is replaced by one
asserting the behaviour - so the file records that the gap closed rather than
quietly losing the note that it existed.

formatVersion moves to 6: additive and omitted when false, but a version 5 reader
would drop it and generate a signature that promises less than the schema does.

403 tests in Schema.Test (6 new), 46 in Schema.Cpp.Test, 201 in SchemaEditor.Test.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AhoPJ5AbxP8QEBNxPQYEPk
@sonarqubecloud

Copy link
Copy Markdown

@matt-edmondson
matt-edmondson merged commit 8c03be7 into main Sep 11, 2026
12 checks passed
@matt-edmondson
matt-edmondson deleted the claude/peaceful-mayer-oo6l2u branch September 11, 2026 00:27
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.

2 participants