Interpolation into Threads.@spawn macro fails for certain kinds of Structs

My understanding is that without interpolation, there is a race condition whereby the object that x refers to might or might not change before the function runs. The interpolation “captures” the binding, guaranteeing that x refers to the object it was bound to at the time of the @spawn macro.

The code below (swapping out func(x) / func($x) demonstrates the difference.

import Base.Threads.@spawn

function func(A)
    A[1] = 90
    return A
end

const N = 100
is_same_object = Vector{Bool}(undef, N);

for i = 1:N
    x = [1,2,3]
    fx = @spawn func(x)
    #fx = @spawn func($x)
    x = [4,5,6]
    x2 = fetch(fx)
    is_same_object[i] = x2 === x
end

count(is_same_object)

If this interpretation is correct, then I think the documentation is misleading:

Values can be interpolated into @spawn via $, which copies the value directly into the constructed underlying closure. This allows you to insert the value of a variable, isolating the aysnchronous code from changes to the variable’s value in the current task.