owned this note changed 2 years ago
Published Linked with GitHub

Reading notes: Language feature: in-place construction

Link to document: https://y86-dev.github.io/blog/safe-pinned-initialization/in-place.html

tags: reading-club

Leave questions, observations, discussion topics below.


Topic

name: prompt


Are in-place constructors similar to alloca?

Yosh: my knowledge of C / C++ is limited, but this seems to give similar vibes as alloca does? Instead of constructing a new thing and returning it, you take a reference to a location and construct the thing there - meaning you never have to move it.

  • (eholk) It's more like placement new in C++. (I don't know if that link is actually good, it was just one that came up relatively high after searching :) )

How is this different from move constructors as well?

mcyoung showed this on twitter recently: alloca in rust using const generics:

fn static_alloca<const N: usize, R>(f: impl FnOnce(&mut [u8]) -> R) -> R {
    let mut buf = [0; N];
    f(&mut buf)
}

eholk: alloca is like malloc for the stack instead of the heap. This is for when you have memory already and want to turn it into a value of type T.

eholk: Big benefit of in-place construction is that it gives you access to your self pointer before it's created.

vincenzo: Main reason is to remove unsafe code in kernel crate.

eholk: Is this removing unsafe, or shuffling it around?

tmandry: Encapsulates unsafe in a macro and Box constructors.

Follow-up question: don't we already have established ways of doing placement-new?

Yosh: I think I was talking with Mara last week who mentioned something like that? My memory is a bit hazy, but I believe there should be ways of achieving placement-new already as well without using unsafe? Or am I completely off?

tmandry: There's Box::new_in, not stable.

tmandry: If you want to construct self-referential types you need in-place construction. We skipped past the overview post that explains this, oops.

eholk: The only way to do self-references is with raw pointers. No way to talk about this using e.g. 'self in Rust.

tmandry: I've seen in a talk about Polonius how we could use the "origins" framing to work toward something like this:

struct Foo {
    data: String,
    subset: &'data str,
}

(To be clear we don't get this with Polonius today!)

Eric was trying to do this yesterday:

struct Foo<F>
where
    F: 'data
{
    data: String,
    subset: F
}

(the idea is F is a future that references data, but data can also be accessed outside the future)

tmandry: Sounds a little like what the yoke crate does.

Details

Yosh: I remember reading their previous post a while back. It didn't make note of any of the problems relating to pin-projections such as what to do about Drop, or #[repr(packed)], or unsafe trait Unpin {}. Idk, it feels like at least from the outset there are important details left unaddressed?

Oh yeah, here's their "safe pin projections" RFC: https://github.com/rust-lang/rfcs/pull/3318. We should probably read this in a future session.

tmandry: Agreed with reading the RFC

PhantomData

Tyler: Why PhantomData here?

pub struct InitClosure<F, T, E>(F, PhantomData<fn(T, E) -> (T, E)>);

Eric: I think it's just because otherwise T and E wouldn't appear in the type.

tmandry: Something something variance putting T and E in both argument and return position makes those type parameters have invariant lifetimes.

So if you have an initializer for Foo<'a> you can't pass it to something that expects you to initialize Foo<'static>, for example.

New syntax

Is it justified? Don't want to spend language complexity budget on niche use case.

Start with macros, then usage can make the case.

Appendix

Rust-for-linux PR: https://github.com/Rust-for-Linux/linux/pull/909 (should be this)

RustConf 2021 talk by Miguel Young de la Sota: https://youtube.com/watch?v=UrDhMWISR3w&feature=share

  • Was that the move constructors talk?
  • yes (:

RFCs by the same author

More discussions on Zulip: https://rust-lang.zulipchat.com/#narrow/stream/213817-t-lang/topic/safe.20initialization

Select a repo