C# codegen: generated `Equals(object)` on `[SpacetimeDB.Type]` structs recurses forever
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 72/100
Research direction
The bug is in the C# source generator at crates/bindings-csharp/BSATN.Codegen/Type.cs, around lines 809-818, where the generated Equals(object) override for structs calls Equals(that_) on a Nullable and recurses. Start by reading that emitter code, then reproduce with the Cell struct and Equals(a, b) example from the issue. Done when the generated override unwraps the nullable value, for example by calling Equals(that_.Value), and the reducer no longer overflows the stack.
Written by the indexing model from the issue text.
Description
Version: SpacetimeDB.Runtime 2.11.*, still on master e596513
Where: crates/bindings-csharp/BSATN.Codegen/Type.cs ~L809-818
public override bool Equals(object? that) {
if (that == null) return false;
var that_ = that as VoipCellCoord?; // for structs this is Nullable<T>
if (((object?)that_) == null) return false;
return Equals(that_); // binds to Equals(object?) again → infinite recursion
}
Repro:
[SpacetimeDB.Type] public partial struct Cell { public int X; public int Y; }
[SpacetimeDB.Reducer]
public static void Repro(ReducerContext ctx) {
Cell a = new() { X = 1 }; Cell? b = new Cell { X = 1 };
var same = Equals(a, b); // object.Equals → Cell.Equals(object) → stack overflow, wasm trap
}
Actual: the reducer traps with a deep recursion through VoipCellCoord__Equals_0 (RhBox at the bottom). Anything
that goes through Equals(object) is affected: object.Equals, EqualityComparer<T>.Default on boxed values,
collections of boxed structs.
Fix: for structs, return Equals(that_.Value); (or that is T t && Equals(t)).
- Dominant language
- Rust
- Stars
- 25.3k
- Forks
- 1.1k
- Avg merge
- 3d 22h
- Merged PRs (30d)
- 61
Getting set up
- Ships a Dockerfile or Docker Compose file
- Has a pull request template
- No contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from clockworklabs/SpacetimeDB
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
clockworklabs/SpacetimeDB#6288 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
clockworklabs/SpacetimeDB#6247 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
clockworklabs/SpacetimeDB#6146 ·
Maintainers usually reply within 1 day
-
CI flake: LintsOpen
Difficulty 1/5 Under an hour Newbie friendliness 88/100
clockworklabs/SpacetimeDB#5985 · 1 comment ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
clockworklabs/SpacetimeDB#5943 · 1 comment ·
Maintainers usually reply within 1 day
All issues in clockworklabs/SpacetimeDB
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 66/100
ActivityWatch/aw-notify-rs#47 · 1 comment ·
-
`inverse()` of a controlled `CUGate` drops the phase parameter γPossibly taken @rupasri118 claimed this today. Openbug mod: circuit
Difficulty 2/5 1-3 hours Newbie friendliness 66/100
Qiskit/qiskit#17223 · 1 comment ·
Maintainers usually reply within 1 day
-
Difficulty 1/5 Under an hour Newbie friendliness 84/100
Maintainers usually reply within 2 days
-
agent:triaged bug bughunt pm:bundler priority:p1
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
SocketDev/socket-patch#1573 · 1 comment ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 62/100
bytecodealliance/rustix#1706 · 1 comment ·
Maintainers usually reply within 11 days