# \`DerefMove\` as two separate traits

**URL:** <https://internals.rust-lang.org/t/derefmove-as-two-separate-traits/16031>\
**Category:** language design\
**Created:** [January 26, 2022, 6:57pm UTC](https://internals.rust-lang.org/t/derefmove-as-two-separate-traits/16031 "2022-01-26T18:57:26Z")\
**Posts on this page:** 19\
**Page:** 1

<div class="post-metadata">

**Author:** ![tema2](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/tema2/32/6498_2.png) [@tema2](https://internals.rust-lang.org/u/tema2)\
**Post date:** [January 26, 2022, 6:57pm UTC](https://internals.rust-lang.org/t/derefmove-as-two-separate-traits/16031/1 "2022-01-26T18:57:26Z")

</div>

Alternatively, we split `DerefMove` into two traits:

```rust
/// trait for moving out of container
trait DerefGet: Deref {
   /// This return layout info of data stored by container
   fn layout(&self) -> Layout;
   /// This returns an actual data pointer. Also, `Unique` from `core::ptr` may be used here.
   fn deref_get(&self) -> *const <Self as Deref>::Target;
   /// This is intended to dispose **empty** container
   unsafe fn drop(*mut self);
}

///trait for moving in a container
trait DerefSet: DerefMut {
   /// prepare the memory region
   fn prepare(&mut self,layout: Layout);
   /// move the value in. Here I would like to use `Unique` too.
   fn deref_set(&mut self,*mut <Self as Deref>::Target);
}

```

And the interesting part:

```rust
...
let data: Box<[u64]> = ...;
let mut data_moved = Box::new();
*data_moved = *data; // tada! [1]
//let data_moved = box *data //this woun't work as of there is no thing which we `DerefSet` yet. [2]
...

```

[1] What is actually happening is:

- dereference operator calls `layout`, gets it, and calls recievers `prepare` with the desired layout. container itself decides how to manage its memory, for example, `Box` has two options: `reallocate` and `reallocate_in_place`... ;
- after that we get the pointer from `data` by `deref_get` and pass in to `deref_set` of `data_moved`;
- the final thing to do is to dispose `data`, but because of one of containers fields has been moved out, for soundness it needs a different `drop` path, which is `unsafe fn drop(*mut self)` from `DerefGet` is.

[2] If we go that far, we face the need of `Placer` trait and placement features, exactly as it used to be in past...

The problem of fallible allocation (can be probably be found when `DerefSet`ting smth. like `[1;10*1024*1024*1024]`) is still there, however:

- The vast majority of use cases deal with `Sized` data =\> `Layout` returned from `DerefGet::layout` is going to be a `const`.
- Also, I don't see any adequate way to support fallible allocation without some crazy syntax and some kind of opinionated signaling involved; given the previous bullet I don't think that in such case we need to do anything else than a `panic` or `handle_alloc_error`.

A `Sized` data example

```rust
let mut b: Box<[u8;10]> = ...;
*b = [10;10]; //Here we used `DerefSet`, layout passing is optimized out.

```

The worst about this is that we don't have fine grained error handling in case of `DerefSet` allocation fails.

---

<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:** [January 26, 2022, 8:12pm UTC](https://internals.rust-lang.org/t/derefmove-as-two-separate-traits/16031/2 "2022-01-26T20:12:49Z")

</div>

- First and foremost, what's the goal here? What's the problem you're trying to solve?
  - I thought `DerefMove`'s goal was to allow (partially) moving out of a `Deref`erencable container, but this has nothing to do with unsized types I see here, nor with partial moves.

- `DerefGet` needs to be `unsafe` (the layout might be wrong, `deref_get` might not return a valid pointer)
- `deref_set` needs to be `unsafe` (the caller might not provide a valid pointer)
- Can't you get the layout from the raw pointers since they need to be valid anyway?
- How is the snippet desugared to use these traits?
- Possible allocation when dereferencing is a deal breaker for me.

---

<div class="post-metadata">

**Author:** ![tema2](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/tema2/32/6498_2.png) [@tema2](https://internals.rust-lang.org/u/tema2)\
**Post date:** [January 26, 2022, 8:43pm UTC](https://internals.rust-lang.org/t/derefmove-as-two-separate-traits/16031/3 "2022-01-26T20:43:05Z")

</div>

> [@SkiFire13](#):
>
> Possible allocation when dereferencing is a deal breaker for me.

That's the serious problem; any thoughts? This is designed to allow moving around unsized data, and currently, this cannot be opted out. Do we a need a way for this?

> [@SkiFire13](#):
>
> - I thought `DerefMove` 's goal was to allow (partially) moving out of a `Deref` erencable container, but this has nothing to do with unsized types I see here, nor with partial moves.
> - `DerefGet` needs to be `unsafe` (the layout might be wrong, `deref_get` might not return a valid pointer)
> - `deref_set` needs to be `unsafe` (the caller might not provide a valid pointer)
> - Can't you get the layout from the raw pointers since they need to be valid anyway?

These are part of `Deref` trait family and, i guess, are allowed to have pretty non-trivial contract:

- all `Layout` s that go in and out both traits must be valid.
- pointers are valid; Moreover, these pointers own what they refer to, we just don't have `&move T` references. Maybe mentioned `Unique<T>` would be better?

> [@SkiFire13](#):
>
> How is the snippet desugared to use these traits?

> [@tema2](#):
>
> ```rust
> let data: Box<[u64]> = ...;
> let mut data_moved = Box::new();
> *data_moved = *data; // tada! [1]
> 
> ```

becomes:

```rust
let data: Box<[u64]> = ...;
let mut data_moved = Box::new();
{
   let mut data = data; //consume data;
   let layout = DerefGet::layout(&data);
   DerefSet::prepare(&mut data_moved,layout); //here is where allocation error might occur
   DerefSet::deref_set(&mut data_moved,DerefGet::deref_get(&data)); //and it's not going to work - we need to change the signature of `deref_get` to reflect ownership transfer
   unsafe { DerefGet::drop(&mut data); /*call the drop glue, and no `Drop::drop` */ }
}

```

> [@SkiFire13](#):
>
> First and foremost, what's the goal here? What's the problem you're trying to solve?

The motivation is to allow `Box` be non magical struct, improve other owning container convenience, allow them to hande unsized data.

Edit: if data contains `Sized` data, the desugaring is even simpler: As of `T: Sized` then its layout is known from both pointers and references, actual `Layout` that must be returned `DerefGet::layout` is known at compile time.

```rust
...
{
   let mut data = data;
   DerefSet::deref_set(&mut data_moved, DerefGet(&data));
   unsafe {DerefGet::drop(&mut data); /* call drop glue*/ }
}
...

```

This avoids risk of allocation, if it is unnecessay.

---

<div class="post-metadata">

**Author:** ![tema2](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/tema2/32/6498_2.png) [@tema2](https://internals.rust-lang.org/u/tema2)\
**Post date:** [January 26, 2022, 10:12pm UTC](https://internals.rust-lang.org/t/derefmove-as-two-separate-traits/16031/4 "2022-01-26T22:12:06Z")

</div>

> [@SkiFire13](#):
>
> - `DerefGet` needs to be `unsafe` (the layout might be wrong, `deref_get` might not return a valid pointer)
> - `deref_set` needs to be `unsafe` (the caller might not provide a valid pointer)

I'm not happy with `deref_set` being `unsafe` because it's called in language level desugaring...

As with `DerefGet` - yes, it is better for it to be `unsafe`.

### More cases to note:

#### sized data & dynamically sized place:

```rust
let data = Box::new([0u64;16]);
let mut data_moved: Box<[u64]> = Box::new();
{
   let mut data = data;
   unsafe {
      DerefSet::prepare(&mut data_move, Layout::for_value(&*data));
      DerefSet::deref_set(&mut *data);
      DerefGet::drop(&mut data; /*drop glue call*/)
   }
}

```

Best about this is that implementor type itself decides, what to do if it is requested to store less or more bytes than it has.

#### unsized data & sized place

I want to forbid it, due to risk of not fitting data into place.

#### unsized data & the stack

In this case we use `unsized_locals` feature.

#### sized data & the stack

```rust
let data = Box::new([]);
{
   let mut data = data;
   unsafe {
      let data_ = core::ptr::read(DerefGet::deref_get(&data));
      DerefGet::drop(&mut data);
      data_
   }
}

```

---

<div class="post-metadata">

**Author:** ![chrefr](https://avatars.discourse-cdn.com/v4/letter/c/e480ec/32.png) [@chrefr](https://internals.rust-lang.org/u/chrefr)\
**Post date:** [January 27, 2022, 1:25am UTC](https://internals.rust-lang.org/t/derefmove-as-two-separate-traits/16031/5 "2022-01-27T01:25:30Z")

</div>

> [@tema2](#):
>
> I'm not happy with `deref_set` being `unsafe` because it's called in language level desugaring...

This is not special; e.g. `Pin::new_unchecked()` is used in the desugaring of `async`.

---

<div class="post-metadata">

**Author:** ![chrefr](https://avatars.discourse-cdn.com/v4/letter/c/e480ec/32.png) [@chrefr](https://internals.rust-lang.org/u/chrefr)\
**Post date:** [January 27, 2022, 1:28am UTC](https://internals.rust-lang.org/t/derefmove-as-two-separate-traits/16031/6 "2022-01-27T01:28:39Z")

</div>

While I definitely support making `Box` less magical, it doesn't allow (AFAIK) moving out unsized values, so a simple `trait DerefMove: Deref where Self::Output: Sized { fn deref_move(self) -> Self::Output; }` is enough.

And even if we want to allow unsized values, something like [1909-unsized-rvalues - The Rust RFC Book](https://rust-lang.github.io/rfcs/1909-unsized-rvalues.html) seems more appropriate.

---

<div class="post-metadata">

**Author:** ![spunit262](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/spunit262/32/5677_2.png) [@spunit262](https://internals.rust-lang.org/u/spunit262)\
**Post date:** [January 27, 2022, 9:06am UTC](https://internals.rust-lang.org/t/derefmove-as-two-separate-traits/16031/7 "2022-01-27T09:06:06Z")

</div>

> [@chrefr](#):
>
> While I definitely support making `Box` less magical, it doesn't allow (AFAIK) moving out unsized values,

It does and it's visible on stable with `Box<dyn FnOnce>`, though is important to note that it's [only logically moved, not physically moved](https://play.rust-lang.org/?version=stable&mode=release&edition=2021&gist=012da1f2cfc9bd0f31981898284865b1). Physically moving a DST is currently only possible with the currently [unsound `unsized_locals`](https://github.com/rust-lang/rust/issues/71416) feature.

> [@tema2](#):
>
> `fn deref_get(&self) -> *const <Self as Deref>::Target;`

This is incompatible with the logical move that `Box<dyn FnOnce>` currently does as `FnOnce`s need to modify themselves. `&mut -> *mut` is the minimum, but as the container will be in a fragile state after the move it should be `*mut -> *mut`.

> [@tema2](#):
>
> `unsafe fn drop(*mut self);`

This should take a `Layout` to allow the possible future addition of thin DST as they will need to read themselves to get their layout, but will be in a invalid state when this is called.

---

<div class="post-metadata">

**Author:** ![tema2](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/tema2/32/6498_2.png) [@tema2](https://internals.rust-lang.org/u/tema2)\
**Post date:** [January 27, 2022, 9:49am UTC](https://internals.rust-lang.org/t/derefmove-as-two-separate-traits/16031/8 "2022-01-27T09:49:25Z")

</div>

> [@spunit262](#):
>
> `FnOnce` s need to modify themselves. `&mut -> *mut` is the minimum, but as the container will be in a fragile state after the move it should be `*mut -> *mut` .

The container will be dropped right after move out, see desugarings. Of course, it would be nice if we would be able to reuse the container, reinitialize it somehow.

> [@spunit262](#):
>
> This should take a `Layout` to allow the possible future addition of thin DST as they will need to read themselves to get their layout, but will be in a invalid state when this is called.

Where can I read about thin DSTs?

---

<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:** [January 27, 2022, 9:56am UTC](https://internals.rust-lang.org/t/derefmove-as-two-separate-traits/16031/9 "2022-01-27T09:56:10Z")

</div>

> [@tema2](#):
>
> That's the serious problem; any thoughts? This is designed to allow moving around unsized data, and currently, this cannot be opted out. Do we a need a way for this?

I think this should not be the default behaviour. A good behaving `*data_moved = *data` should never allocate.

Moreover I don't see the problem this is solving. What's the problem with `data_moved = data` or `data_moved = std::mem::take(&mut data)`? You're just introducing an additional, useless, allocation.

> [@tema2](#):
>
> These are part of `Deref` trait family and, i guess, are allowed to have pretty non-trivial contract:

Being a part of the `Deref` family doesn't magically introduce any contract. That's done through function signatures and `unsafe` annotations.

> [@tema2](#):
>
> The motivation is to allow `Box` be non magical struct

This isn't currently addressed, at least for the most part. `Box` is special because dereferencing it **creates a place** that you're allowed to move out from. This is different from just moving the `T` out of it, which can be done with a simple `fn into_inner(self) -> T` function, for example it allows you to:

- move out of some fields, but not others, leaving the `T` in a partially initialized state (just like it's possible for stack allocated stuff);
- reinitialize those fields, without having to allocate new `Box`es or moving the fields that weren't previously moved;
- dropping the other fields in place, without moving them to the stack.

Moreover you can create mutable references to different fields without saving the result of `deref_mut` in some variable first. See [this playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=0a98254454a2f06875bac2bc0e13ce82) for example

So, how are these snippet desugared under your proposal? How can they keep their current semantics and performance?

```rust
struct Foo {
    s1: String,
    s2: String,
}

let mut b = Box::new(Foo {
    s1: String::from("s1"),
    s2: String::from("s2"), 
});

let _s2 = b.s2; // consume only one field

// Here `b` is partially initialized. Note that the `Box` is not deallocated!

b.s2 = String::from("s3"); // You can also put stuff back!

let s1 = &mut b.s1;
let s2 = &mut b.s2;
consume((s1, s2));

consume(b); // and now you can use `b` again because it's fully initialized again.

```

```rust
struct Unsized {
    s: String,
    rest: [u8],
}

let mut b: Box<Unsized> = todo!();
let _s = b.s; // only moves the sized field to the stack!

```

> [@tema2](#):
>
> improve other owning container convenience, allow them to hande unsized data.

What are the current problems with them? And how are they solved by your proposal?

> [@tema2](#):
>
> I'm not happy with `deref_set` being `unsafe` because it's called in language level desugaring...

So how do you handle an user calling `DerefSet::deref_set(&mut some_box, std::ptr::null_mut())`?

> [@tema2](#):
>
> ```rust
> let data = Box::new([0u64;16]);
> let mut data_moved: Box<[u64]> = Box::new();
> {
> let mut data = data;
> unsafe {
> DerefSet::prepare(&mut data_move, Layout::for_value(&*data));
> DerefSet::deref_set(&mut *data);
> DerefGet::drop(&mut data; /*drop glue call*/)
> }
> }
> 
> ```

How is this any better than `data_moved = data`? It even does an additional allocation! What problem is this even solving?

> [@tema2](#):
>
> In this case we use `unsized_locals` feature.

That's an incomplete feature that's nowhere near being done due to limitations in LLVM and other problems. Your feature should likely not depend on it.

---

<div class="post-metadata">

**Author:** ![tema2](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/tema2/32/6498_2.png) [@tema2](https://internals.rust-lang.org/u/tema2)\
**Post date:** [January 27, 2022, 12:56pm UTC](https://internals.rust-lang.org/t/derefmove-as-two-separate-traits/16031/10 "2022-01-27T12:56:44Z")

</div>

> [@SkiFire13](#):
>
> What are the current problems with them? And how are they solved by your proposal?

Recently, I was writing an application where I needed a `List<dyn Any>`: I coudn't make it to work because of the list contents was unsized. Now I want to add a mechanism to allow underlying `Node` type to be moved out.

> [@SkiFire13](#):
>
> So how do you handle an user calling `DerefSet::deref_set(&mut some_box, std::ptr::null_mut())` ?

Indeed, now I see your point. What do you think about safe trait with all methods being unsafe? What would you expect from such a thing?

> [@SkiFire13](#):
>
> How is this any better than `data_moved = data` ? It even does an additional allocation! What problem is this even solving?

It works like I described only in case of moving sized value into unsized place, if both the value and the place are `Sized`, then its no different from what you are comparing it to.

> [@SkiFire13](#):
>
> `Box` is special because dereferencing it **creates a place** that you're allowed to move out from. This is different from just moving the `T` out of it, which can be done with a simple `fn into_inner(self) -> T` function, for example it allows you to: ...

That's really an argument against such split. I haven't come up with any scheme for splitting the work in code from playground. The best I could mind of is just making `DerefGet::deref_get` to produce a place... But then it's old `DerefMove`, for `Sized` types... It seems that what you have requested will require a lot ground work.

> [@SkiFire13](#):
>
> That's an incomplete feature that's nowhere near being done due to limitations in LLVM and other problems. Your feature should likely not depend on it.

I think, moving out with `DerefGet` onto stack should be part of `unsized_locals` feature: it trivially uses this feature, but involves creation of an unsized local. E.g. this ability should be available only with both features active.

---

<div class="post-metadata">

**Author:** ![mathstuf](https://avatars.discourse-cdn.com/v4/letter/m/958977/32.png) [@mathstuf](https://internals.rust-lang.org/u/mathstuf)\
**Post date:** [January 27, 2022, 1:00pm UTC](https://internals.rust-lang.org/t/derefmove-as-two-separate-traits/16031/11 "2022-01-27T13:00:42Z")

</div>

> [@tema2](#):
>
> I'm not happy with `deref_set` being `unsafe` because it's called in language level desugaring...

I think they need to be unsafe because what is the state of things after this?

```rust
let layout = DerefGet::layout(&data);
target.prepare(layout);
// `deref_set` is never called.

```

What is:

- the state of `data`?
- the state of `target`?
- the state of whatever was in `target` before?

So even if there were types to do things like "guarantee this pointer was returned from `DerefGet` or the like", I think the functions need to be `unsafe`. What if these impls `panic!`? Will the `Drop` impls be able to handle that case?

---

<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:** [January 27, 2022, 1:25pm UTC](https://internals.rust-lang.org/t/derefmove-as-two-separate-traits/16031/12 "2022-01-27T13:25:13Z")

</div>

> [@tema2](#):
>
> Recently, I was writing an application where I needed a `List<dyn Any>` : I coudn't make it to work because of the list contents was unsized. Now I want to add a mechanism to allow underlying `Node` type to be moved out.

That seems different than `Box`'s magic, and I don't see what's blocking you from implementing yourself, other than not being able to use the `*foo` syntax.

> [@tema2](#):
>
> Indeed, now I see your point. What do you think about safe trait with all methods being unsafe? What would you expect from such a thing?

- `unsafe` on a method means that the caller needs to prove some invariants, but not the method;
- `unsafe` on a trait means that the implementer needs to prove some invariants, including on the methods, but not the caller.

So `DerefSet::deref_set` needs to be `unsafe` because the caller needs to provide a valid pointer, and the `DerefGet` trait needs to be marked `unsafe` because the implementation must return a valid pointer in `DerefGet::deref_get`.

> [@tema2](#):
>
> It works like I described only in case of moving sized value into unsized place

Then as long as `data` contains a `Sized` type then `data_moved = data` is better than what you're describing.

> [@tema2](#):
>
> That's really an argument against such split. I haven't come up with any scheme for splitting the work in code from playground. The best I could mind of is just making `DerefGet::deref_get` to produce a place... But then it's old `DerefMove` , for `Sized` types... It seems that what you have requested will require a lot ground work.

There's a reason `Box` is still special after all...

---

<div class="post-metadata">

**Author:** ![tema2](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/tema2/32/6498_2.png) [@tema2](https://internals.rust-lang.org/u/tema2)\
**Post date:** [January 27, 2022, 1:33pm UTC](https://internals.rust-lang.org/t/derefmove-as-two-separate-traits/16031/13 "2022-01-27T13:33:33Z")

</div>

> [@mathstuf](#):
>
> What is:
> 
> - the state of `data` ?
> - the state of `target` ?
> - the state of whatever was in `target` before?

- Not changed, just got layout;
- Up to the `target`: most probably it should make its underlying memory be able to hold the value of `data`; so, `realloc(_in_place)`, `dealloc\alloc` pair, erasing old value (with `drop`) - these should be fine.
- Up to the `target`: `forget`, `drop_in_place`, send it somewhere, etc.

In case of panic after (of inside of) the `prepare` method, nothing happens - move itself hasn't been performed. The boundaries I imagine are following:

- `DerefGet::deref_get` is assumed to deinitialize the data, so no `drop` shall be called.
- `DerefSet::deref_set` is assumed to (re)initialize its target by its end, so also nothing special.
- The case of `deref_set` panics itself is harder: probably another `drop` method in the trait, aka `drop_empty`...

Lossy boundaries for library authors, but good ones for actual consumers

---

<div class="post-metadata">

**Author:** ![tema2](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/tema2/32/6498_2.png) [@tema2](https://internals.rust-lang.org/u/tema2)\
**Post date:** [January 27, 2022, 1:45pm UTC](https://internals.rust-lang.org/t/derefmove-as-two-separate-traits/16031/14 "2022-01-27T13:45:22Z")

</div>

Now, it appears to me that I have chosen wrong separation of concepts - instead of `DerefGet` and `DerefSet` there may be `DerefMove` and `DerefUnsized`:

```rust
trait DerefMove: Deref {
   fn deref_move(self: Unique<Self>) -> Unique<<Self as Deref>::Target>; //`Unique` is from `libcore`
   unsafe fn drop_empty(self: Unique<Self>);
}
unsafe trait DerefUnsized: DerefMove {
  fn prepare(&mut self,layout: Layout);
}

```

Now, we can opt out from working with unsized values, share more methods found out to be required during discussion, and have situation with `unsafe` clear.

Edit: `DerefUnsize::get_layout` got removed as of [this](https://internals.rust-lang.org/t/derefmove-as-two-separate-traits/16031/17)

---

<div class="post-metadata">

**Author:** ![mathstuf](https://avatars.discourse-cdn.com/v4/letter/m/958977/32.png) [@mathstuf](https://internals.rust-lang.org/u/mathstuf)\
**Post date:** [January 27, 2022, 2:06pm UTC](https://internals.rust-lang.org/t/derefmove-as-two-separate-traits/16031/15 "2022-01-27T14:06:19Z")

</div>

> [@tema2](#):
>
> Not changed, just got layout;

So…a type implementing this has to stash the `Layout` somewhere then. Do I need to have an `Option<Layout>` in my type to track whether `prepare` has been called or not? If that's all it does, why is it its own method instead of "also pass `Layout` to what needs it"?

---

<div class="post-metadata">

**Author:** ![tema2](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/tema2/32/6498_2.png) [@tema2](https://internals.rust-lang.org/u/tema2)\
**Post date:** [January 27, 2022, 2:20pm UTC](https://internals.rust-lang.org/t/derefmove-as-two-separate-traits/16031/16 "2022-01-27T14:20:55Z")

</div>

Imagine you store an unsized slice, to move it somewhere, you need to first notify that place, that it's expected to have certain ammount of memory cleaned.

> [@mathstuf](#):
>
> also pass `Layout` to what needs it

I haven't picked this way because I wanted to have "failed to `prepare` =\> no move occurs", as the API currently stands it's impossible to handle preparation error, but I wanted a room for this.

> [@mathstuf](#):
>
> So…a type implementing this has to stash the `Layout` somewhere then.

In bad cases, when we cannot recompute layout each time we use `DerefGet`, yes; However the implementation for slices (and trait objects?) might be cheap enough.

---

<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:** [January 27, 2022, 2:40pm UTC](https://internals.rust-lang.org/t/derefmove-as-two-separate-traits/16031/17 "2022-01-27T14:40:10Z")

</div>

I still don't understand what's this problem for `Layout`. As I already said:

> Can't you get the layout from the raw pointers since they need to be valid anyway?

A valid raw pointer allow you create a reference and use it to call [`Layout::for_value`](https://doc.rust-lang.org/stable/std/alloc/struct.Layout.html#method.for_value). Not to mention that there's an unstable [`Layout::for_value_raw`](https://doc.rust-lang.org/stable/std/alloc/struct.Layout.html#method.for_value_raw)

---

<div class="post-metadata">

**Author:** ![tema2](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/tema2/32/6498_2.png) [@tema2](https://internals.rust-lang.org/u/tema2)\
**Post date:** [January 27, 2022, 2:59pm UTC](https://internals.rust-lang.org/t/derefmove-as-two-separate-traits/16031/18 "2022-01-27T14:59:24Z")

</div>

Thanks, I took a look at these functions in past, but thought that there may be surprising cases when these may produce wrong layout, so I, influenced by old placement feature, decided to write my own layout exchanging. Fixed the newer API.

---

<div class="post-metadata">

**Author:** ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)\
**Post date:** [April 27, 2022, 2:59pm UTC](https://internals.rust-lang.org/t/derefmove-as-two-separate-traits/16031/19 "2022-04-27T14:59:54Z")

</div>

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.
