apple / swift-numerics

Advanced mathematical types and functions for Swift
Apache License 2.0
1.69k stars 147 forks source link

[BigInt tests] ✅ Copy on write #249

Open LiarPrincess opened 1 year ago

LiarPrincess commented 1 year ago

Please read the #242 Using tests from “Violet - Python VM written in Swift” before.


All pass.

🐰 Discussion

Those tests are a bit difficult to grasp. Especially because they start with unary operations. I think it would be better if you started with binary operations:

func test_add_toCopy_doesNotModifyOriginal() {
  // int + int
  var value = BigInt(Int.max)
  var copy = value
  _ = copy + self.int
  XCTAssertEqual(value, BigInt(Int.max))
}

func test_addEqual_toCopy_doesNotModifyOriginal() {
  // int + int
  var value = BigInt(Int.max)
  var copy = value
  copy += self.int
  XCTAssertEqual(value, BigInt(Int.max))
}

The general idea is that the original value should not be modified when we perform operation on copy. It will not test if the copy was created before (var copy = value) or during the write (actual COW), but it will test that the copy was made at some point.

The general idea is that BigInt will probably allocate on the heap. What happens when we modify the heap value? All of them change? Or maybe only the BigInt that was used in operation? It is easy to break the invariant if you implement COW by hand.

Alternatively you could make BigInt non-copyable (move-only). Then you chose: 1) copy heap on BigInt copy (no COW)

  1. reference count, so that BigInt is a struct with explicit copy/retain (COW, acting like a smart pointer, RAII etc.)

Obviously move-only is extremely un-ergonomic, so…