Unsafe collection which allows immutable access while also allowing push()
Safety First

Unfortunately, programming in unsafe Rust requires respecting a number of rules; and you have broken at least one here.

Rust memory safety is based on the principle of Aliasing XOR Mutability, which is enforced as much as possible at compile-time for obvious performance reasons. When you wish to shift the responsibility from compile-time to run-time, you need to inform the compiler about it at the type level, lest it infers properties about the code that do not hold.

For interior mutability, use UnsafeCell.

This is the basic block that is used by all abstractions which defer the enforcement of the principle to run-time. For example, here is AtomicBool:

#[cfg(target_has_atomic = "8")]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct AtomicBool {
    v: UnsafeCell&lt;u8&gt;,
}


Thus, your type should be:

pub struct UnsafeHolder&lt;T&gt; {
    items: UnsafeCell&lt;Vec&lt;Box&lt;(T,String)&gt;&gt;&gt;,
}




Clean-up

UnsafeCell comes with a get method: UnsafeCell::get(&amp;self) -&gt; *mut T, and thus your change_mut function is unnecessary:

pub fn add_element(&amp;self, element: T, key: String) {
    if !unsafe { &amp; *self.items.get() }.iter().any(|i| i.1 == key) {
        let items = unsafe { &amp;mut *self.items.get() };
        items.push(Box::new((element, key)));
    }
}




Nits and bits

Your add_element method should indicate when insertion fails; silent failures make programs harder to debug.

It seems strange to me to pass the element before the key; most APIs seem to do the reverse so I would advise following in their steps.

The complexity of your look-up is O(N), so that inserting repeatedly has O(N2) complexity; if you were sorting by key look-up could be O(log N) instead, and repeated insertion O(N log N).

I recommend avoiding unnecessary parentheses (such as in if !(...)); they clutter the code for no obvious gain.



Final Word

If you wish to venture into the world of unsafe, I recommend reading the Nomicon. Until Rust gets official unsafe semantics, it is probably the best reference about the dos and don'ts.