The fifth convention: whether a call changes what it is called on - #162
Merged
Conversation
…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
|
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.



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()asconst, 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
Voidchanges 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.Cppemits it as the trailingconst, which is what lets a caller holding aconstreference call it at all:§3's acceptance test now asserts the document's text including that
const, andAQueryCannotYetSayItLeavesTheReceiverUnchangedis replaced byAQuerySaysItLeavesTheReceiverUnchanged— 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
formatVersionmoves 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 inQueryFunctionTests), 46 inSchema.Cpp.Test, 201 inSchemaEditor.Test. Whole solution builds with 0 warnings.🤖 Generated with Claude Code
https://claude.ai/code/session_01AhoPJ5AbxP8QEBNxPQYEPk
Generated by Claude Code