@@ -677,6 +677,40 @@ test "clear" {
677677 inspect(m.contains("MoonBit " |> i), content="true ")
678678}
679679
680+ ///|
681+ test "copy sparse set only copies occupied key slots" {
682+ let m : HashSet [MyString ] = new_hashset(default_init_capacity)
683+ fn i(s) {
684+ MyString ::MyString (s)
685+ }
686+
687+ m.add("a" |> i)
688+ m.add("ab" |> i)
689+ m.add("bc" |> i)
690+ m.add("cd" |> i)
691+ m.add("abc" |> i)
692+ m.add("abcdef" |> i)
693+ m.remove("ab" |> i)
694+ let copied = m.copy()
695+ inspect(copied.length(), content="5")
696+ inspect(copied.capacity(), content="8")
697+ inspect(physical_equal(copied.psls, m.psls), content="false ")
698+ inspect(physical_equal(copied.hashes, m.hashes), content="false ")
699+ inspect(physical_equal(copied.keys, m.keys), content="false ")
700+ let mut occupied = 0
701+ for idx in 0..<m.capacity {
702+ @test.assert_eq(copied.psls[idx], m.psls[idx])
703+ @test.assert_eq(copied.hashes[idx], m.hashes[idx])
704+ if m.psls[idx] != empty_psl {
705+ occupied += 1
706+ assert_true(copied.keys[idx] == m.keys[idx])
707+ }
708+ }
709+ inspect(occupied, content="5")
710+ inspect(copied.contains("ab" |> i), content="false ")
711+ inspect(copied.contains("abcdef" |> i), content="true ")
712+ }
713+
680714///|
681715/// Insert a key into the hash set and returns whether the key was successfully added.
682716///
@@ -752,7 +786,11 @@ pub fn[K] HashSet::copy(self : HashSet[K]) -> HashSet[K] {
752786 }
753787 self.psls.blit_to(other.psls, len=self.capacity)
754788 self.hashes.blit_to(other.hashes, len=self.capacity)
755- UninitializedArray ::unsafe_blit(other.keys, 0, self.keys, 0, self.capacity)
789+ for i in 0..<self.capacity {
790+ if self.psls[i] != empty_psl {
791+ other.keys[i] = self.keys[i]
792+ }
793+ }
756794 other
757795}
758796
0 commit comments