-
Notifications
You must be signed in to change notification settings - Fork 180
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improving or getting rid of the DataPayload RcStruct variant #1262
Comments
In the future, or perhaps as part of this issue, I would like to see the ability to plug a custom allocator into I also want to point out that in many cases |
Good point, we can get away with just using EncodeAsVarULE for this (which will be derivable eventually) |
Yes; I think this works for simpler types. For complex types that aren't compatible with EncodeAsVarULE, we can use Postcard. |
2021-11-05:
Conclusion: move forward with "Get rid of RcStruct" |
Prioritization input: unlikely to be blocking people in November, perhaps later |
icu4x/provider/core/src/erased.rs Lines 80 to 87 in b51dccd
icu4x/provider/core/src/serde.rs Lines 289 to 296 in b51dccd
Looking at this we may still need a |
Hmm, I think we can handle these by using projections instead, actually. Annoyingly this means that the steps are more inextricably linked so it's harder to do incrementally. |
I have this, but I'm hitting the HRTB resolution error (same one that's affecting my ZCF code) again. Need to file an issue. impl<'data, M> crate::dynutil::UpcastDataPayload<'data, M> for SerdeSeDataStructMarker
where
M: DataMarker<'data>,
M::Cart: IsCovariant<'data>,
for<'a> &'a <M::Yokeable as Yokeable<'a>>::Output: serde::Serialize,
for<'a> &'a <M::Yokeable as Yokeable<'a>>::Output: IsCovariant<'a>,
{
fn upcast(other: DataPayload<'data, M>) -> DataPayload<'data, SerdeSeDataStructMarker> {
use crate::data_provider::DataPayloadInner;
match other.inner {
DataPayloadInner::RcStruct(yoke) => {
// same thing as before
let cart: Rc<dyn SerdeSeDataStruct<'data> + 'data> = Rc::from(yoke);
DataPayload::from_partial_owned(cart)
}
DataPayloadInner::Owned(yoke) => {
let inner = DataPayloadInner::Owned(yoke.project(|payload , _| SerdeSeDataStructDynRef(Box::new(payload))));
DataPayload {inner}
}
DataPayloadInner::RcBuf(yoke) => unimplemented!(),
}
}
} |
Yeah, ideally we can solve upcast with a projection. One problem though is that you can't upcast or downcast something to ErasedDataStruct that has a non-static lifetime, which projection requires since projection operates on the shortened lifetime. Note that currently upcasting to ErasedDataStruct is only implemented on |
Filed rust-lang/rust#90638 about the ICE/error Current progress stashed in https://github.com/Manishearth/icu4x/tree/rm-rcstruct |
Another use case: for Unicode Properties FFI, I want to map-project |
Given that getting rid of the lifetime is going to be an annoying PR, do you think it's worth first getting rid of the Cart in a separate PR? That sounds much more manageable and gets us the immediate things we need without requiring a much gnarlier set of changes. |
Does the |
Yes because the cart stays the same type, I think |
Cool. It solves some short term problems, but does it get us closer to the eventual goal of removing the lifetime? If so, then go for it. |
It doesn't get us further, and we're going to be getting rid of Cart anyway, so it makes that PR a little bit simpler :) But it might not be worth doing if we're going to clean up that lifetime soon. |
The approach of getting rid of RcStruct is blocked on an ICE, right? Are there any other workarounds, and do you have a sense of when the ICE might be fixed? |
So, I'm not sure. The incremental approach I was taking is blocked on an ICE but it's quite possible there's another approach that isn't. I actually think we may be able to get rid of the lifetime and the cart without immediately deleting RcStruct as well (and only using RcStruct for upcasting), This would require getting rid of the cart before the lifetime so I think it's worth trying! |
The steps would be:
|
I might take a crack at step 1, especially since it's purely internal |
Finished step 0: #1278 |
Steps 1-2 were easier than I thought: #1279 |
Step 3: #1297 |
Step 4: #1299 |
Related: #1151
(I've been discussing this with @sffc and wanted to have this on file so I don't forget the details)
DataPayload
has the following innards:icu4x/provider/core/src/data_provider.rs
Lines 98 to 105 in 0c855b1
The Owned and RcBuf variants are relatively easy to deal with and make use of Yoke as originally intended.
RcStruct
is weird, it's essentially intended for creating a local data struct (say,Foo<'a>
), and storing a borrowed reference to it. Typically,RcStruct
will be something likeRcStruct<Yoke<Foo<'static>, Rc<Foo<'data>>>
, where'data
is borrowing from potentially local data.This has a couple problems:
'data
(I think this is my fault), which we also use in data structs to refer to the lifetime of their backing zero-copy buffer. This lifetime in general complicates a lot of stuffM::Cart
) to deal with, making code more confusing. We have to deal with two kinds of "cart" types -- the allocating cart types thatYoke
typically expects, and the "inner" cart types that data payloads use (that get allocated behind anRc
)There are a couple things we can do here to improve the status quo:
Keep the lifetime, but get rid of
M::Cart
This fixes #1151. Essentially, the only reason we need cart in the yoke is to call its destructor.
RcStruct
can instead be written as:and have the same effect. Note that
dyn Drop
isn't actually legal, but we can define a dummy internal trait with no methods that is blanket implemented (trait objects always have destructors in their vtables), and addYoke
helpers that can erase carts with it.Get rid of
RcStruct
We can get rid of this entirely. This cleans up the lifetimes and types significantly (and fixes #1151), but it means that if someone wishes to create a
DataPayload
from locally borrowed data, they must construct it asOwned
data. We could potentially add aToOwned
implementation (or something similar) to theZeroCopyFrom
custom derive that makes this pleasant to use when working with borrowed data.We can potentially make this more pleasant in the future; another way (this may be more expensive than
ToOwned
, worth measuring) would be to postcard serialize the object and then construct the data payload as anRcBuf
deserialization.I am leaning towards getting rid of
RcStruct
entirely.Feedback requested from
The text was updated successfully, but these errors were encountered: