Skip to content

Name the ToString override a node has to carry - #1042

Merged
Rafael-SOWNet merged 1 commit into
masterfrom
docs/node-must-override-tostring
Aug 23, 2026
Merged

Rafael-SOWNet merged 1 commit into
masterfrom
docs/node-must-override-tostring

Conversation

@Rafael-SOWNet

Copy link
Copy Markdown
Member

Docs/Contributing/AddingNode.cs exists to list every place a new node must be taught about —
AGENTS.md says to read it before adding one. It does not mention ToString.

Every one of the 69 node types carries public override string ToString() => Stringize();:

$ grep -rn "override string ToString" Sources/AngouriMath --include=*.cs | grep -c "=> Stringize();"
69
$ grep -c "ToString" Sources/AngouriMath/Docs/Contributing/AddingNode.cs
0

Why omitting it is worse than a wrong string

Entity is a record, so C# synthesises ToString from PrintMembers, which prints every public
property. Two of Entity's are Entity-valued:

Functions/Evaluation/Evaluation.Definition.cs:139:  public Entity Evaled => …
Functions/Evaluation/Evaluation.Definition.cs:168:  public Entity InnerSimplified => …

So the synthesised ToString calls ToString on each of them, which calls it on theirs, and so on.
A node missing the override does not print the wrong thing — it exhausts the stack, and it does so
at a call site nowhere near the node, which is the hard kind of failure to trace back.

Nothing enforces it. It is not a compiler error, no analyzer checks it, and the 69 existing
occurrences are the only reason it has never bitten: every node was copied from one that had it,
which is exactly the kind of invariant that survives until the first person who does not copy.

Scope

One line of guidance in AddingNode.cs, +6 lines. No code, no behaviour change, no
BREAKING-CHANGES.md entry. Touches no file any other open PR touches.

Found while measuring what an Entity subclass outside the kernel assembly needs in order to work —
#1026, and the design document for it is
#1040.

Every one of the 69 node types has 'public override string ToString() =>
Stringize();' and this guide, which exists to list every place a new node must
be taught about, does not mention it.

It is not optional and it is not a compiler error when missed. Entity is a
record, so C# synthesises ToString from PrintMembers, which prints every public
property; Evaled and InnerSimplified are public and Entity-valued, so each of
them calls ToString again. A node that omits the override does not print
wrongly -- it exhausts the stack, at a call site nowhere near the node.

Found while measuring what an Entity subclass outside the kernel assembly needs
in order to work (#1026).
@Rafael-SOWNet
Rafael-SOWNet merged commit e5fe8c9 into master Aug 23, 2026
31 checks passed
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