NSDiffableDataSourceSnapshot bug?

i found something really odd in NSDiffableDataSourceSnapshot behaviour. the tl;dr version is that this:

                snapshot.moveItem("one", afterItem: "two")
                dataSource.apply(snapshot)

gives correct result, while this:

                var snapshotCopy = snapshot
                snapshotCopy.moveItem("one", afterItem: "two")
                dataSource.apply(snapshotCopy)

gives incorrect result, despite being semantically equivalent. snapshot is a true value type, right?

it is as odd as if i wrote:

var b = a
b += 1
a = b

and got a different result in "a" compared to "a += 1"

minimal source fragment attached (doesn't need nib files/storyboards)
========
Code Block
import UIKit
class ViewController: UIViewController {
var tv: UITableView!
var dataSource: UITableViewDiffableDataSource<String, String>!
override func viewDidLoad() {
super.viewDidLoad()
tv = UITableView(frame: view.bounds)
tv.autoresizingMask = [.flexibleWidth, .flexibleHeight]
view.addSubview(tv)
tv.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
var originalSnapshot = NSDiffableDataSourceSnapshot<String, String>()
originalSnapshot.appendSections(["***"])
originalSnapshot.appendItems(["one", "two", "three"])
dataSource = UITableViewDiffableDataSource<String, String>(tableView: tv) { (tv, indexPath, item) -> UITableViewCell? in
let cell = tv.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = item
return cell
}
dataSource.apply(originalSnapshot)
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
var snapshot = self.dataSource.snapshot()
snapshot.insertItems(["four"], afterItem: "one")
if true {
var snapshotCopy = snapshot
snapshotCopy.moveItem("one", afterItem: "two")
self.dataSource.apply(snapshotCopy)
/* gives incorrect result:
two, one, three */
}
else {
snapshot.moveItem("one", afterItem: "two")
self.dataSource.apply(snapshot)
/* gives correct result:
four, two, one, three */
}
}
}
}
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
window = UIWindow(frame: UIScreen.main.bounds)
window!.rootViewController = ViewController()
window!.makeKeyAndVisible()
return true
}
}

filed as FB7875053

interestingly changing:
Code Block
var snapshot = self.dataSource.snapshot()

to:
Code Block
var snapshot = originalSnapshot

fixes the issue.

all in all this looks like a "value-typeness" bug in NSDiffableDataSourceSnapshot.

NSDiffableDataSourceSnapshot bug?
 
 
Q