They are not needed, but these `unsafe` blocks actually do make a performance difference. The trick being used here is to represent sparse sets using uninitialized memory. It's described in more detail here: http://research.swtch.com/sparse

In this case, I can actually produce evidence. The first column is without `unsafe` and the second column is the code as you see it:

```
anchored_literal_long_match             264 ns/iter (+/- 2)                    165 ns/iter (+/- 4)
anchored_literal_long_non_match        5867 ns/iter (+/- 8)                   5822 ns/iter (+/- 45)
anchored_literal_short_match            232 ns/iter (+/- 8)                    161 ns/iter (+/- 2)
anchored_literal_short_non_match        495 ns/iter (+/- 1)                    424 ns/iter (+/- 3)
easy0_1K                               1808 ns/iter (+/- 111) = 566 MB/s      1277 ns/iter (+/- 170) = 801 MB/s
easy0_32                                330 ns/iter (+/- 2) = 96 MB/s          276 ns/iter (+/- 3) = 115 MB/s
easy0_32K                             48878 ns/iter (+/- 650) = 670 MB/s     33323 ns/iter (+/- 968) = 983 MB/s
easy1_1K                               1881 ns/iter (+/- 556) = 544 MB/s      1794 ns/iter (+/- 684) = 570 MB/s
easy1_32                                391 ns/iter (+/- 93) = 81 MB/s         341 ns/iter (+/- 70) = 93 MB/s
easy1_32K                             49735 ns/iter (+/- 2484) = 658 MB/s    48367 ns/iter (+/- 2864) = 677 MB/s
hard_1K                               47163 ns/iter (+/- 268) = 21 MB/s      35070 ns/iter (+/- 169) = 29 MB/s
hard_32                                1840 ns/iter (+/- 38) = 17 MB/s        1389 ns/iter (+/- 17) = 23 MB/s
hard_32K                            1497950 ns/iter (+/- 5921) = 21 MB/s   1112845 ns/iter (+/- 2605) = 29 MB/s
literal                                 142 ns/iter (+/- 2)                    131 ns/iter (+/- 0)
match_class                            1403 ns/iter (+/- 6)                   1394 ns/iter (+/- 6)
match_class_in_range                   1448 ns/iter (+/- 3)                   1347 ns/iter (+/- 4)
medium_1K                             17310 ns/iter (+/- 255) = 59 MB/s      17475 ns/iter (+/- 166) = 58 MB/s
medium_32                               888 ns/iter (+/- 29) = 36 MB/s         835 ns/iter (+/- 34) = 38 MB/s
medium_32K                           542510 ns/iter (+/- 2595) = 60 MB/s    550793 ns/iter (+/- 2491) = 59 MB/s
no_exponential                       274104 ns/iter (+/- 466)               278257 ns/iter (+/- 906)
not_literal                            1104 ns/iter (+/- 5)                   1080 ns/iter (+/- 4)
one_pass_long_prefix                    548 ns/iter (+/- 5)                    379 ns/iter (+/- 3)
one_pass_long_prefix_not                520 ns/iter (+/- 2)                    409 ns/iter (+/- 2)
one_pass_short_a                       1326 ns/iter (+/- 18)                  1291 ns/iter (+/- 8)
one_pass_short_a_not                   1945 ns/iter (+/- 21)                  1585 ns/iter (+/- 29)
one_pass_short_b                        913 ns/iter (+/- 3)                    816 ns/iter (+/- 8)
one_pass_short_b_not                   1242 ns/iter (+/- 7)                   1401 ns/iter (+/- 9)
replace_all                            1353 ns/iter (+/- 13)                  1291 ns/iter (+/- 11)               
```

My guess as to what's happening---particularly in the `hard` benchmarks---is that the `mem::uninit` saves a lot of time by not initializing threads that never need to be initialized, particularly with larger regexps (like the `hard` benchmark) with a lot of instructions.

I've included a justification in a comment and a link to Russ Cox's article.