# How to do an in-place mapping of values in containers from a T to a newtype wrapper of T?

**URL:** <https://internals.rust-lang.org/t/how-to-do-an-in-place-mapping-of-values-in-containers-from-a-t-to-a-newtype-wrapper-of-t/24607>\
**Category:** Uncategorized\
**Created:** [September 19, 2026, 12:01pm UTC](https://internals.rust-lang.org/t/how-to-do-an-in-place-mapping-of-values-in-containers-from-a-t-to-a-newtype-wrapper-of-t/24607 "2026-09-19T12:01:33Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![Sawyer47](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/sawyer47/32/13467_2.png) [@Sawyer47](https://internals.rust-lang.org/u/Sawyer47)\
**Post date:** [September 19, 2026, 12:01pm UTC](https://internals.rust-lang.org/t/how-to-do-an-in-place-mapping-of-values-in-containers-from-a-t-to-a-newtype-wrapper-of-t/24607/1 "2026-09-19T12:01:33Z")

</div>

Hi!

I wonder how to map a container in-place from type `T` to a `repr(transparent)` wrapper of `T` that establishes some invariant - purely as an optimization so that I do not need to rewrite the entire container into a new one. I very vaguely remember there being some functionality for it in `std`, although it might have been years ago and it definitely has been removed. I doubt there is a general solution, but what about the most common containers from `std`: `Vec` and `HashMap`? How to implement the following code in Rust?

```rust
#![feature(hash_map_macro)]
use std::{collections::HashMap, hash_map};

#[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Clone)]
#[repr(transparent)]
struct SortedVec<T>(Vec<T>);

fn into_sorted_vec(mut value: Vec<u64>) -> SortedVec<u64> {
    value.sort_unstable();
    SortedVec(value)
}

fn map_vec(input: Vec<Vec<u64>>) -> Vec<SortedVec<u64>> {
    todo!("How to implement without allocating extra memory?");
}

fn map_hm<K>(input: HashMap<K, Vec<u64>>) -> HashMap<K, SortedVec<u64>> {
    todo!("How to implement without allocating extra memory?");
}

fn main() {
    let vec1: Vec<Vec<u64>> = vec![vec![3, 2, 1], vec![6, 5, 4]];
    let vec2_expected: Vec<SortedVec<u64>> =
        vec![SortedVec(vec![1, 2, 3]), SortedVec(vec![4, 5, 6])];

    let vec1_mapped = map_vec(vec1);
    assert_eq!(vec1_mapped, vec2_expected);

    let hm1: HashMap<&str, Vec<u64>> = hash_map! {"one" => vec![3,2,1], "two" => vec![6,5,4]};
    let hm1_mappedd = map_hm(hm1);
    let hm2_expected: HashMap<&str, SortedVec<u64>> =
        hash_map! {"one" => SortedVec(vec![1, 2, 3]), "two" => SortedVec(vec![4, 5, 6])};
    assert_eq!(hm1_mappedd, hm2_expected);
}

```

---

<div class="post-metadata">

**Author:** ![ProgramCrafter](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/programcrafter/32/13494_2.png) [@ProgramCrafter](https://internals.rust-lang.org/u/ProgramCrafter)\
**Post date:** [September 19, 2026, 12:22pm UTC](https://internals.rust-lang.org/t/how-to-do-an-in-place-mapping-of-values-in-containers-from-a-t-to-a-newtype-wrapper-of-t/24607/2 "2026-09-19T12:22:01Z")

</div>

`input.into_iter().map(into_sorted_vec).collect::<Vec<_>>()` will not allocate (IIRC at best-effort basis though).

It's implemented at [in\_place\_collect.rs - source](https://doc.rust-lang.org/src/alloc/vec/in_place_collect.rs.html).

---

<div class="post-metadata">

**Author:** ![SkiFire13](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/skifire13/32/7579_2.png) [@SkiFire13](https://internals.rust-lang.org/u/SkiFire13)\
**Post date:** [September 19, 2026, 12:33pm UTC](https://internals.rust-lang.org/t/how-to-do-an-in-place-mapping-of-values-in-containers-from-a-t-to-a-newtype-wrapper-of-t/24607/3 "2026-09-19T12:33:20Z")

</div>

And if you don't want to rely on a best effort feature you can do a dance with `Vec::into_raw_parts`, casting the raw pointer and then using `Vec::from_raw_parts`.

AFAIK there's no equivalent for `HashMap`

---

<div class="post-metadata">

**Author:** ![Vorpal](https://avatars.discourse-cdn.com/v4/letter/v/aca169/32.png) [@Vorpal](https://internals.rust-lang.org/u/Vorpal)\
**Post date:** [September 19, 2026, 5:06pm UTC](https://internals.rust-lang.org/t/how-to-do-an-in-place-mapping-of-values-in-containers-from-a-t-to-a-newtype-wrapper-of-t/24607/5 "2026-09-19T17:06:18Z")

</div>

Maybe I'm missing something, but why wouldn't transmute be sound here? Assuming that no safety variants of the transparent wrapper are violated, and that the wrapper has the same layout (so no funny NonZero, pattern types, etc). Shouldn't `Container<T>` and `Container<WrapperT>` have the exact same memory layout and valid bit patterns?

This isn't needed for Vec (as previous answers show) but why wouldn't it not be sound for e.g. HashMap?

---

<div class="post-metadata">

**Author:** ![jrose](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jrose/32/9591_2.png) [@jrose](https://internals.rust-lang.org/u/jrose)\
**Post date:** [September 19, 2026, 5:11pm UTC](https://internals.rust-lang.org/t/how-to-do-an-in-place-mapping-of-values-in-containers-from-a-t-to-a-newtype-wrapper-of-t/24607/6 "2026-09-19T17:11:39Z")

</div>

As an example, if the _keys_ are what you're reinterpreting, the new type might have a different Eq or Hash. Or the HashMap might use std::any::type\_name as part of the seeding process. So it's not the case _by default_ that you can just transmute a container and get a valid container back.

---

<div class="post-metadata">

**Author:** ![kpreid](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kpreid/32/8484_2.png) [@kpreid](https://internals.rust-lang.org/u/kpreid)\
**Post date:** [September 19, 2026, 5:19pm UTC](https://internals.rust-lang.org/t/how-to-do-an-in-place-mapping-of-values-in-containers-from-a-t-to-a-newtype-wrapper-of-t/24607/7 "2026-09-19T17:19:05Z")

</div>

Additionally:

- The compiler is allowed to use a different layout for `Container<Foo>` and `Container<Bar>` unless `Container` and its components all use a repr that is more constrained than default `repr(Rust)`
- Somewhat less plausible, but: the container could be storing a `fn(T) -> bool` or a `dyn Trait<T>` for some purpose, at which point compatibility depends not just on the layout of `T` but the ABI of `T`.

Broadly, there’s just no way to _know from the outside_ that none of these problems exist for an arbitrary container type, except that type’s documentation.

Ideally, we would have the “safe transmute project”'s traits and containers could expose a trait to convert them in this way only if doing so was sound. But we don’t.

---

<div class="post-metadata">

**Author:** ![Vorpal](https://avatars.discourse-cdn.com/v4/letter/v/aca169/32.png) [@Vorpal](https://internals.rust-lang.org/u/Vorpal)\
**Post date:** [September 19, 2026, 5:20pm UTC](https://internals.rust-lang.org/t/how-to-do-an-in-place-mapping-of-values-in-containers-from-a-t-to-a-newtype-wrapper-of-t/24607/8 "2026-09-19T17:20:21Z")

</div>

That is a fair point, didn't think of that. But it would be good to have some way to do this zero cost for all the std containers. It would likely have to be unsafe for many containers though, since it would be infeasible to determine if different Hash, Ord etc are equivalent.

---

<div class="post-metadata">

**Author:** ![Vorpal](https://avatars.discourse-cdn.com/v4/letter/v/aca169/32.png) [@Vorpal](https://internals.rust-lang.org/u/Vorpal)\
**Post date:** [September 19, 2026, 5:23pm UTC](https://internals.rust-lang.org/t/how-to-do-an-in-place-mapping-of-values-in-containers-from-a-t-to-a-newtype-wrapper-of-t/24607/9 "2026-09-19T17:23:57Z")

</div>

> [@kpreid](#):
>
> - The compiler is allowed to use a different layout for `Container<Foo>` and `Container<Bar>` unless `Container` and its components all use a repr that is more constrained than default `repr(Rust)`

We could (and IMO should) limit that. It would have to be after all layout attributes and traits are resolved (to not run into issues with `<T as Trait>::Type` being different, just though of that one). But if the only thing that differs are repr transparent wrappers it would be useful if they would be laid out the same.

---

<div class="post-metadata">

**Author:** ![Vorpal](https://avatars.discourse-cdn.com/v4/letter/v/aca169/32.png) [@Vorpal](https://internals.rust-lang.org/u/Vorpal)\
**Post date:** [September 19, 2026, 5:24pm UTC](https://internals.rust-lang.org/t/how-to-do-an-in-place-mapping-of-values-in-containers-from-a-t-to-a-newtype-wrapper-of-t/24607/10 "2026-09-19T17:24:35Z")

</div>

> [@kpreid](#):
>
> Ideally, we would have the “safe transmute project”'s traits and containers could expose a trait to convert them in this way only if doing so was sound. But we don’t.

I haven't heard anything about that for quite some time, what happened to it?

---

<div class="post-metadata">

**Author:** ![robofinch](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/robofinch/32/13874_2.png) [@robofinch](https://internals.rust-lang.org/u/robofinch)\
**Post date:** [September 19, 2026, 5:39pm UTC](https://internals.rust-lang.org/t/how-to-do-an-in-place-mapping-of-values-in-containers-from-a-t-to-a-newtype-wrapper-of-t/24607/11 "2026-09-19T17:39:11Z")

</div>

Unsafe code can’t depend on a covariant type parameter remaining the same, due to subtyping between distinct higher-ranked function types that AFAIK could have different trait implementations. (But it could be a requirement for logical correctness.)

---

<div class="post-metadata">

**Author:** ![robofinch](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/robofinch/32/13874_2.png) [@robofinch](https://internals.rust-lang.org/u/robofinch)\
**Post date:** [September 19, 2026, 5:41pm UTC](https://internals.rust-lang.org/t/how-to-do-an-in-place-mapping-of-values-in-containers-from-a-t-to-a-newtype-wrapper-of-t/24607/12 "2026-09-19T17:41:58Z")

</div>

I think it could suffice for the type to _not_ be invariant over the relevant generic parameter. (And using an associated type forces invariance, of course.) `repr(transparent)` should even have the same ABI, right…? In which case the “only” thing that would be needed is a compiler guarantee.

---

<div class="post-metadata">

**Author:** ![the8472](https://avatars.discourse-cdn.com/v4/letter/t/0ea827/32.png) [@the8472](https://internals.rust-lang.org/u/the8472)\
**Post date:** [September 19, 2026, 6:06pm UTC](https://internals.rust-lang.org/t/how-to-do-an-in-place-mapping-of-values-in-containers-from-a-t-to-a-newtype-wrapper-of-t/24607/13 "2026-09-19T18:06:09Z")

</div>

layout for `Foo<A>` and `Foo<B>` can differ even if `A` and `B` have the same layout.

> `repr(transparent)` should even have the same ABI, right…?

If A is transparent around B then `Foo<A>` and `Foo<B>` still _could_ have different layout. In practice they'll be the same most of the time, but you can provoke it with layout randomization.

> <https://github.com/rust-lang/rust/blob/feaadeeaca7db0594da854e7c8c07495341c7439/tests/ui/layout/randomize.rs#L31-L34>

`repr(Rust)` makes very few guarantees at all.

---

<div class="post-metadata">

**Author:** ![Vorpal](https://avatars.discourse-cdn.com/v4/letter/v/aca169/32.png) [@Vorpal](https://internals.rust-lang.org/u/Vorpal)\
**Post date:** [September 19, 2026, 6:12pm UTC](https://internals.rust-lang.org/t/how-to-do-an-in-place-mapping-of-values-in-containers-from-a-t-to-a-newtype-wrapper-of-t/24607/14 "2026-09-19T18:12:54Z")

</div>

> [@the8472](#):
>
> `repr(Rust)` makes very few guarantees at all.

While this is generally good to allow additional optimisations to be added, does it serve any purpose here (other than "because we can"?)

I think that it would be useful to add a _narrow_ guarantee that if the only thing that differs for a concrete fully resolved type is repr transparent wrappers, then the types have the same layout.

This would mean that transmute is _possible_, but the actual container type (e.g. HashMap) would _also_ need to guarantee this for it to be then be sound.

---

<div class="post-metadata">

**Author:** ![the8472](https://avatars.discourse-cdn.com/v4/letter/t/0ea827/32.png) [@the8472](https://internals.rust-lang.org/u/the8472)\
**Post date:** [September 19, 2026, 6:24pm UTC](https://internals.rust-lang.org/t/how-to-do-an-in-place-mapping-of-values-in-containers-from-a-t-to-a-newtype-wrapper-of-t/24607/15 "2026-09-19T18:24:55Z")

</div>

From a user perspective you cannot reason about the public interface of `Foo<T>` that

> surely the layout must stay the same when Ta and Tb are transparent

because `Foo` could use associated types internally to have another field vary based on those types.

So even if such a rule existed it wouldn't help you with transmuting collections owned by std.

---

<div class="post-metadata">

**Author:** ![Vorpal](https://avatars.discourse-cdn.com/v4/letter/v/aca169/32.png) [@Vorpal](https://internals.rust-lang.org/u/Vorpal)\
**Post date:** [September 19, 2026, 6:38pm UTC](https://internals.rust-lang.org/t/how-to-do-an-in-place-mapping-of-values-in-containers-from-a-t-to-a-newtype-wrapper-of-t/24607/16 "2026-09-19T18:38:00Z")

</div>

> [@the8472](#):
>
> So even if such a rule existed it wouldn't help you with transmuting collections owned by std.

I think you didn't read my last paragraph:

> [@Vorpal](#):
>
> This would mean that transmute is _possible_, but the actual container type (e.g. HashMap) would _also_ need to guarantee this for it to be then be sound.

Today, I cannot write a HashMap that guarantees such transmutes even if I wanted to, but with language guarantees it would be _possible_. And then std could add such guarantees. For HashMap in particular it would also need to specify that the implementations of Hash and Eq need to be the same for example.

---

<div class="post-metadata">

**Author:** ![the8472](https://avatars.discourse-cdn.com/v4/letter/t/0ea827/32.png) [@the8472](https://internals.rust-lang.org/u/the8472)\
**Post date:** [September 19, 2026, 6:42pm UTC](https://internals.rust-lang.org/t/how-to-do-an-in-place-mapping-of-values-in-containers-from-a-t-to-a-newtype-wrapper-of-t/24607/17 "2026-09-19T18:42:10Z")

</div>

But you can. If you need a guaranteed layout there are other reprs for that.

---

<div class="post-metadata">

**Author:** ![Vorpal](https://avatars.discourse-cdn.com/v4/letter/v/aca169/32.png) [@Vorpal](https://internals.rust-lang.org/u/Vorpal)\
**Post date:** [September 19, 2026, 6:50pm UTC](https://internals.rust-lang.org/t/how-to-do-an-in-place-mapping-of-values-in-containers-from-a-t-to-a-newtype-wrapper-of-t/24607/18 "2026-09-19T18:50:25Z")

</div>

I can make my container `repr(C)`, yes. But as far as I can tell it doesn't help today if the inner type is a transparent repr around a rust repr. And it is that case I would like to work better. I might not control that inner repr Rust.

---

<div class="post-metadata">

**Author:** ![the8472](https://avatars.discourse-cdn.com/v4/letter/t/0ea827/32.png) [@the8472](https://internals.rust-lang.org/u/the8472)\
**Post date:** [September 19, 2026, 7:00pm UTC](https://internals.rust-lang.org/t/how-to-do-an-in-place-mapping-of-values-in-containers-from-a-t-to-a-newtype-wrapper-of-t/24607/19 "2026-09-19T19:00:35Z")

</div>

`A` and `#[repr(transparent)] Wrapper<A>` are guaranteed to have the same layout. And the `repr(C)` layout algorithm is guaranteed to only take field order, alignment and size into account. So the container would get the same layout if it is `repr(C)`.

There two things that can prevent transmuting, for generic `Foo<T>` and `T=X`, and `T=Z` it's both that

- `Foo` can change its layout - we can suppress that with `repr(C)`
- `X` and `Z` can have different layouts even when we naively wouldn't expect it just by looking at their fields (e.g. randomization). We can suppress this either by also making the inner types `repr(C)` or by making one a `repr(transparent)` wrapper around the other

---

<div class="post-metadata">

**Author:** ![Vorpal](https://avatars.discourse-cdn.com/v4/letter/v/aca169/32.png) [@Vorpal](https://internals.rust-lang.org/u/Vorpal)\
**Post date:** [September 19, 2026, 8:00pm UTC](https://internals.rust-lang.org/t/how-to-do-an-in-place-mapping-of-values-in-containers-from-a-t-to-a-newtype-wrapper-of-t/24607/20 "2026-09-19T20:00:54Z")

</div>

If that is correct, then I'm happy with that. But I'm not sure where your second bullet point is guaranteed. I read the docs for transmute and the linked to section in the nomicon. Basically I'm not sure where it is stably guaranteed that a `repr(Rust)` inside a `repr(transparent)` inside a `repr(C)` will have the same layout as if the middle `repr(transparent)` is removed.

The nomicon reads:

> So how do you know if the layouts are the same? For `repr(C)` types and `repr(transparent)` types, layout is precisely defined. But for your run-of-the-mill `repr(Rust)`, it is not. Even different instances of the same generic type can have wildly different layout.

To me that doesn't clearly say what happens if you nest and mix them.

- [transmute in std::mem - Rust](https://doc.rust-lang.org/std/mem/fn.transmute.html)
- [Transmutes - The Rustonomicon](https://doc.rust-lang.org/nomicon/transmutes.html)

(The transmute safety docs in std are all too vague for my liking. I would prefer a clear numbered list of requirements that need to be upheld.)

---

<div class="post-metadata">

**Author:** ![the8472](https://avatars.discourse-cdn.com/v4/letter/t/0ea827/32.png) [@the8472](https://internals.rust-lang.org/u/the8472)\
**Post date:** [September 19, 2026, 8:09pm UTC](https://internals.rust-lang.org/t/how-to-do-an-in-place-mapping-of-values-in-containers-from-a-t-to-a-newtype-wrapper-of-t/24607/21 "2026-09-19T20:09:20Z")

</div>

The rust reference is a better choice here if you want an authoritative source:

- [repr(C)](https://doc.rust-lang.org/reference/type-layout.html#reprc-structs) - only looks at field order, size, alignment
- [repr(transparent)](https://doc.rust-lang.org/reference/type-layout.html#the-transparent-representation) - have the same layout (and thus size and alignment) as the inner

The inner-most `repr(Rust)` can do whatever it wants, it won't affect the choices of the structs it is nested inside. And it cannot suddenly make a different decisions because you can always take references to the inners, so `C -> transparent -> rust` and `C -> rust` must be the same within one compilation.

[Next page](https://internals.rust-lang.org/t/how-to-do-an-in-place-mapping-of-values-in-containers-from-a-t-to-a-newtype-wrapper-of-t/24607.md?page=2)
