-
-
Notifications
You must be signed in to change notification settings - Fork 405
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
[[HostDefined]]
Refactor
#3370
[[HostDefined]]
Refactor
#3370
Conversation
52e4428
to
94a917f
Compare
Codecov ReportAttention:
Additional details and impacted files@@ Coverage Diff @@
## main #3370 +/- ##
==========================================
- Coverage 45.40% 44.82% -0.59%
==========================================
Files 483 488 +5
Lines 49790 50499 +709
==========================================
+ Hits 22609 22637 +28
- Misses 27181 27862 +681
☔ View full report in Codecov by Sentry. |
Currently `[[HostDefined]]` doesn't permit you to mutably borrow two objects from the `[[HostDefined]]` field since the `FxHashMap` is wrapped under a `GcRefCell`. This commit instead wraps all `Box<dyn NativeObject>` entries with a `GcRefCell`, permitting a more granular borrowing scheme. Additionally, this commit takes the opportunity to provide automatic downcasting on the `insert` and `remove` methods for `[[HostDefined]]`.
94a917f
to
72e5a2d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Downcasting on insert
and delete
looks great! However, I'm having second thoughts about having that amount of granularity on the API.
My problem comes from the thought that we'd be worsening the API for users that just want to store one or two types.
On the other hand, if a user wants to mutably borrow two separate types from the map, they can just put both in a wrapper type, then insert that instead, which should allow the same use case. Another workaround would be to just borrow the map multiple times. That should be a lot easier to handle than having to deal with 2 levels of borrowing
(borrowed map + borrowed type, borrowed map + mutably borrowed type, mutably borrowed map + borrowed type, mutably borrowed map + mutably borrowed type)
The primary pain point (for us) with the current implementation is that we cannot mutably borrow two host-defined objects (defined by separate extensions) in a single function. The possible pain points with the proposed implementation are:
I think with perhaps clearer documentation on the borrowing semantics (something that was still lacking with the current implementation wrt to borrowing 2 or more mutable entries in host-defined), this change could still be seen as an improvement over the current API. |
Yeah, and I'd argue this is a design problem, not an API problem. This would still happen if this was a simple Leaving that aside, I think a better solution to this would be to expose the |
(Prefixing my response: I'm still fairly new to Rust so please forgive my ignorance to existing libraries, common design patterns, etc)
Would it? In Rust, what I'd expect is to be given a
But is this possible? As I understand currently, the interface we expose with |
Rust doesn't allow borrowing two mutable entries to the hashmap at the same time, even if the keys aren't equal.
I think this is solvable with a use std::any::TypeId;
trait NativeTuple: Sealed {
type BorrowMutTuple<'a>;
fn as_type_ids() -> Vec<TypeId>;
}
// Impls for tuples of size 1 to N
impl HostDefined {
// More methods
fn get_many_mut<Tup: NativeTuple>(&mut self) -> Tup::BorrowMutTuple<'_> {
// Impl
}
} Or something like that, which I think it's pretty feasible. I'll try to come up with a prototype today. |
Thanks for letting me know, I forgot that
Whoa, this is really neat. If you're strapped for time, I'd be happy to try and prototype it myself! (Though I may up asking a lot of stupid questions over discord) |
Sure, you can give it a go! It'll be a bit hard because of limitations from rustc around const generics, pub fn get_many_mut<Tup, const SIZE: usize>(&mut self) -> Option<Tup::BorrowedMutTuple<'_>>
where
Tup: Tuple<SIZE>,
{
let ids = Tup::as_type_ids();
let refs: [&TypeId; SIZE] = ids.iter().collect::<Vec<_>>().try_into().expect("tuple should be of size `SIZE`");
self.types
.get_many_mut(refs)
.and_then(|anys| Tup::mut_refs_from_anys(anys))
}
pub trait Tuple<const SIZE: usize> {
type BorrowedMutTuple<'a>;
fn as_type_ids() -> Vec<TypeId>;
fn mut_refs_from_anys(
anys: [&'_ mut Box<dyn NativeObject>; SIZE],
) -> Option<Self::BorrowedMutTuple<'_>>;
} Ideally we'd have the |
Closing in favour of #3460 |
Context
Currently
HostDefined
doesn't permit you to mutably borrow two objects from the[[HostDefined]]
field since theFxHashMap
is wrapped under aGcRefCell
.Description
This PR instead wraps all
Box<dyn NativeObject>
entries in theFxHashMap
with aGcRefCell
, permitting a more granular borrowing scheme for each entry.Additionally, this PR takes the opportunity to provide automatic downcasting on the
insert
andremove
methods forHostDefined
.