Analysis: On the first pass, the key for _bagForFreeVariables is the unbound Y, so on the second pass with Y is bound to 1, the key in _bagForFreeVariables is (incorrectly) mutated to 1. This doesn't happen in the second case because the unbound X, not Y, is stored as the key. (This doesn't happen in C# because the dictionary stores the hash of unbound Y for the key and doesn't look at the value on the second pass.)
To fix, it is tempting to use copy_term when storing the key in _bagForFreeVariables, but then this will incorrectly give 2 answers:
bagof(X, (X = Y ; X = Y), B).
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Analysis: On the first pass, the key for _bagForFreeVariables is the unbound Y, so on the second pass with Y is bound to 1, the key in _bagForFreeVariables is (incorrectly) mutated to 1. This doesn't happen in the second case because the unbound X, not Y, is stored as the key. (This doesn't happen in C# because the dictionary stores the hash of unbound Y for the key and doesn't look at the value on the second pass.)
To fix, it is tempting to use copy_term when storing the key in _bagForFreeVariables, but then this will incorrectly give 2 answers:
bagof(X, (X = Y ; X = Y), B).