Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upPlacement protocol should not consume Placer #1286
Comments
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
The issue description isn't clear about whether it is asking for the argument to be Obviously some use cases would not be satisfied by requiring (This should mesh in with the Allocator design, where I am currently planning to use |
This comment has been minimized.
This comment has been minimized.
|
Being one who proposed it initially, I’m personally very strongly in favour (of |
This comment has been minimized.
This comment has been minimized.
That's because I haven't made up my mind on that yet. One such alternative would be leaving the signature to be |
This comment has been minimized.
This comment has been minimized.
|
Doesn't malloc use |
This comment has been minimized.
This comment has been minimized.
|
I don't really know what you mean. If this is about "allocators that can't be behind a |
This comment has been minimized.
This comment has been minimized.
bluss
commented
Sep 29, 2015
|
You need to be very careful about evaluation order and panic safety, as well as forcing the placer to be used:
How do we handle panics in for just
This cannot be allowed, would it leave an unitinialized slot? |
This comment has been minimized.
This comment has been minimized.
|
That's what All of this is completely independent of whether the first step consumes the |
This comment has been minimized.
This comment has been minimized.
|
@bluss I see what you mean, but I don’t think it is a problem, because the protocol explicitly addresses preconditions for panic safety:
-- Last paragraph of EDIT: actually it might be worse than I initially thought, because destructors are safe to not run now ( e.g. let something = Something::new();
let place = something.make_place();
// place relies on destructors running for panic safety (e.g. decreasing length in vector case)
mem::forget(place);
panic!();
// destructor for Something reads uninitialized data? |
This comment has been minimized.
This comment has been minimized.
bluss
commented
Sep 29, 2015
|
@nagisa Thanks, looks like I didn't realize this was well enough covered, it's hopefully a matter of adjusting the mockup implementations and it should be possible to solve with the protocol. Not sure the protocol is at risk because of |
This comment has been minimized.
This comment has been minimized.
|
Just a note that the way to make |
This comment has been minimized.
This comment has been minimized.
FWIW, I created one for TypedArena and had no issues with consuming the |
This comment has been minimized.
This comment has been minimized.
|
Yes, because the Placer is a |
This comment has been minimized.
This comment has been minimized.
|
I can't fully articulate this, but |
This comment has been minimized.
This comment has been minimized.
|
Ugh, you're right, if it takes Luckily, this is a local change, it doesn't affect the type (so it doesn't affect callers and data strutures) and it is only necessary if you want to use placement syntax. Still sad. And I had all but convinced myself that |
This comment has been minimized.
This comment has been minimized.
|
If you have an &Arena, you cannot call any method on it that requires On Sun, Oct 4, 2015, 7:31 AM rkruppe notifications@github.com wrote:
|
This comment has been minimized.
This comment has been minimized.
|
Probably the only thing you can’t do with |
This comment has been minimized.
This comment has been minimized.
|
The trait would still be implemented for |
This comment has been minimized.
This comment has been minimized.
|
@rkruppe I was playing around with this last night. I'm a little worried that we would not want to make this change without higher kinded types (HKT). But, my opinion has revised somewhat over the course of writing this comment and trying to make demonstrative examples. Maybe we should make the change you suggest, under the expectation that it might cause some pain in the short term, but in the longer term it is the "right thing" and will yield better code once we do have HKT (assuming that comes in the future). (Explanation follows) In particular: we want the pub struct VecEndPlace<'a, T:'a> {
v: &'a mut Vec<T>,
}
impl<'a, T> Placer<T> for &'a mut Vec<T> {
type Place = VecEndPlace<'a, T>;
fn make_place(self) -> Self::Place {
self.reserve(1);
VecEndPlace { v: self }
}
}If we try to change the impl<T> Placer<T> for Vec<T> {
type Place<'a> = VecEndPlace<'a, T>; // <-- needs HKT!
fn make_place<'a>(&'a mut self) -> Self::Place<'a> {
self.reserve(1);
VecEndPlace { v: self }
}
}Now, there is a way to get this to While trying to fix this, I tried having it pass impl<'a, T:'a> Placer<T> for &'a mut Vec<T> {
type Place = VecEndPlace<'a, T>;
fn make_place(&mut self) -> Self::Place {
self.reserve(1);
VecEndPlace { v: *self }
}
}Unfortunately that does not compile, due to a lifetime inference failure, shown here: http://is.gd/35E1lk Frustrated by the latter, which seems like a case of "this should obviously work", I resorted to a transmute of the impl<'a, T:'a> Placer<T> for &'a mut Vec<T> {
type Place = VecEndPlace<'a, T>;
fn make_place(&mut self) -> Self::Place {
self.reserve(1);
VecEndPlace { v: unsafe { ::std::mem::transmute::<&mut Vec<T>, &'a mut Vec<T>>(*self) } }
}
}This does "work" unsoundly: http://is.gd/KvlwI8 ... but it scares the hell out of me because it is unsound.
(One option that I did not try: remove the lifetime parameter from If you or others have another way to address this problem, I would appreciate you demonstrating it by modifying the following running example (which uses the current Anyway, as I said at the beginning, my opinion has changed somewhat over the course of writing this comment. (Originally I thought that this example was a deal-breaker for the change you suggest, but then I did the experiments above. I am willing to use workarounds, and continue doing |
This comment has been minimized.
This comment has been minimized.
|
It seems we are in violent agreement. Your first option is basically everything I want. I'm just thinking beyond that, how real code will look when using placement syntax liberally, and I'm unhappy that it will probably be littered with As I said, I am not insisting on Admittedly, it makes for a rather strange protocol if the signature says |
This comment has been minimized.
This comment has been minimized.
|
If we want |
This comment has been minimized.
This comment has been minimized.
|
That's a good point, and AFAIK the first solid argument for by-value |
This comment has been minimized.
This comment has been minimized.
|
@arielb1 I don’t see how not consuming |
This comment has been minimized.
This comment has been minimized.
|
Actually |
This comment has been minimized.
This comment has been minimized.
|
Is |
This comment has been minimized.
This comment has been minimized.
|
Some relevant IRC discussion. |
nagisa
referenced this issue
Dec 2, 2015
Closed
Implement placement-in protocol for relevant data structures #30172
This comment has been minimized.
This comment has been minimized.
|
Could someone list the arguments for making |
This comment has been minimized.
This comment has been minimized.
Its taking |
This comment has been minimized.
This comment has been minimized.
|
@nagisa you sure? If |
This comment has been minimized.
This comment has been minimized.
|
Ah, of course. I’m dumb, and shouldn’t comment on things without checking them again if I hadn’t seen them for a month. Sorry! |
This comment has been minimized.
This comment has been minimized.
|
@Stebalien I think it hasn't changed much since @rkruppe wrote the description of the issue. Namely this sentence:
You've already noted that you would prefer
... so the remaining item is allocators that aren't Sad to admit as the author of the current Allocator RFC, I have not yet taken the time to personally experiment with mixing together placement-in and allocators in the manner described elsewhere. I hope to get a chance to do so, but I also don't mind when our awesome community beats me to the punch when it comes to things like this. :) |
This comment has been minimized.
This comment has been minimized.
|
Actually, allocators are why I first asked. As noted in #1401, let b = BoxPlace(HEAP) <- value;However, we can also do something like let b: Box<_> = HEAP.alloc() <- valueWhich gets rid of the problem of taking |
This comment has been minimized.
This comment has been minimized.
|
Methods have auto-ref, so obviously they would address this (that's exactly why |
This comment has been minimized.
This comment has been minimized.
|
try!(vec.insert(n)) <- value;which reserves a slot and moves things to the right. The placer does nothing and neither does the place (which simply points to the free slot) unless it is dropped in which case it moves things back and reduces the length by one. Since the placer cannot allocate memory if you want to do error handling, the placer would have to manually track if it has already been called once and abort the process in this case. Unless |
This comment has been minimized.
This comment has been minimized.
|
It also prevents the Placer and Place from being the same object which is what one wants if the real |
This comment has been minimized.
This comment has been minimized.
|
Or another example: try!(Rc::with_pool(allocator)) <- obj;In this case it is impossible to call the Placer twice because the first call consumes the memory pool. |
This comment has been minimized.
This comment has been minimized.
|
These are nice example. I could quibble a bit with each, but collectively and together with the examples earlier in this discussion, they make pretty clear that by-value self can also be valuable. Additionally, So, I hereby officially propose shifting the focus of this issue from "make |
nrc
added
the
T-lang
label
Aug 22, 2016
bors
added a commit
to rust-lang/rust
that referenced
this issue
Apr 4, 2018
This comment has been minimized.
This comment has been minimized.
|
Closing as this is moot now. |
rkruppe commentedSep 18, 2015
This came up in the discussion of #1228, but it's mostly independent from the syntax change proposed there. Currently creating a
Placefor "placement box" will consume the value that produces the place (the one that's written out in the placement expression, i.e.PLACEinbox (PLACE) EXPR). This hasn't been an issue so far because the only implementation (in std and, as far as I can tell, on GitHub overall) inExchangeHeapSingletonwhich isCopy. That type (and its public name,boxed::HEAP) is hanging by a thread though,box thingis widely preferred toin (HEAP) thingorin HEAP { thing }orHEAP <- thingor any variant of that.Some hypothetical types that would implement
Placerin the future (such as&Arenaand the results ofmap.entry(k),vec.back()) would likely beCopyor inherently "one-off", but other possible uses of placement box would be ruled out by takingself. Examples raised in #1228 arevec <- thing;(instead ofvec.push(thing)),set <- thing;and (disclaimer: my example and pet interest) allocators that can't be behind a&reference.@pnkfelix said: