-
Notifications
You must be signed in to change notification settings - Fork 16
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
multiple borrows extension #5
Conversation
I tried to write a function that receives an
|
First, about your current code:
I think there's 2 distinct usecases here:
The latter is the simpler, I think:
The tuple case is a little more complicated. Essentially you'd want a (maybe?) sealed trait -- I know there's a trick, though I've never used it -- that is implemented for each tuple arity from 0 to 12, and then a function making use of that special trait:
And the trait would look something like (unless 2 traits would be better?):
Note: this could be implemented for all arities with a macro, or using I note that the 2 duplicate checks both rely on local arrays, so there's probably some common code which can be extracted there. I'd rather have the more generic solutions than specialized implementations for 2 and 3, if that makes sense? Let me know if you'd like to work on either array or tuple support. |
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.
Hi,
I see that you are pushing changes that are not quite going in the direction I was thinking -- as illustrated in my previous comment.
I think it would be best to agree on the direction before you put too much work in this.
Cheers.
src/ghost_cell.rs
Outdated
} | ||
} | ||
Some(()) | ||
// TODO: if the array is large enough, sort the values instead. |
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.
That's a good point, sorting is probably less efficient on small arrays.
Do you have a rough idea of where the tipping point would be?
Yeah, sorry. As you see this is commit is pretty incomplete. I didn't realize that pushing it to github will immediately add it to the pull request. I'll wait until I have more complete code before pushing it to github in the future. I basically just worked first on making macros work, and left cleaning it up and making it do the right thing for later. I figured it's better to have separate commits than commit things all together. Do you prefer to have an associated method or free function? Right now it's an associated method ( On the other side, having it as a free function might contaminate the namespace too much, and this function isn't a very important function. In any case, having both is redundant. I just didn't want to delete the free-function version of the macro just so I didn't lose it. I'll clean up and work on your feedback soon (hopefully). |
Now the code should be better. Now that there's a trait for the relevant tuples, I think that having the I'm not sure whether to call it just It might nice to implement the same trait for arrays as well, when I get to implementing it for arrays, because then the Also, I think I'll move all of the feature-gated code to a single module. It will save lots of What do you think? |
should I convert this into a draft pull request? It's still not final. |
Hi! I am not very used to github flows, but if there's a draft function it may nice, as it clearly indicates the status of the PR. Otherwise, as long as we both agree that the PR is a work in progress, it's fine for me. I just want to make sure to calibrate expectations so that you're not waiting for me to merge while I'm waiting for you to complete some work -- let's make sure to be explicit about where we stand. Regarding your remarks, I think we're on the same wavelength:
Regarding the traits, I was thinking that it would be nice to implement them for a variety of types, and notably a variety of values and references:
The latter two, the "Values" 4 and 5, are the problem. You need
I'll just list the two versions close to each others so they can be compared:
And the mutable version:
Among those, I think the first alternative, taking So I'd lean slightly towards having |
I actually haven't thought of having I have a few questions about the different types you suggest implementing multiple borrowing for. First of all, all of the immutable borrows seem less useful to me, because that's already easily implementable. If you have some ghost cells, you can already immutably borrow them at the same time, without worrying about gathering them up into a tuple and without worrying about the possibility any of them were the same ghost cell. In addition, I'm not sure if options 1,2,3 are useful. It seems that in order to use them, the ghost cells have to be stored in the exact way that they will be borrowed. That is, if you use option 2, you have a I guess the benefit of options 1,2,3 is that they should probably be implemented as just a cast, removing any overhead apart for the duplicate check. However, I'm unsure that that's safe rust. Even if About option 4, I'm unsure how to implement it. It seems it can implemented as a cast as well. However, implementing it without a cast, I would like to have some I saw you suggested using |
The cast issue seems to be even more complicated than I thought. https://users.rust-lang.org/t/transmuting-types-with-repr-transparent-parameters/26499 |
It seems I misunderstood. The RFC (https://rust-lang.github.io/rfcs/1758-repr-transparent.html) says that |
I'm not sure if it's a problem; I can't think of Unless the clashes are prevalent, I'd favor keeping the shorter name, as that's going to be used a lot.
I fully agree they are safer to implement, and in the fact the lack of I thought of implementing them for two reasons:
For me, those are good reasons to do it... but this doesn't mean YOU have to. If you prefer to focus on the mutable case, that's perfectly fine with me.
Indeed. It's not exactly "earth-shattering". It's easy to implement, though, no duplicate check needed, for example, and once you have the traits, you might as well. Once again, just because I think they'd be nice to provide doesn't mean YOU have to provide them. I am thinking allowed here.
That's a good question, I'm not exactly sure. It's certainly the entire purpose of
I think the only two options would be I am not sure which is best, per se. I think we can rely on One possibility would be to test with MIRI and see if the Stacked Borrow model complains with either implementation. In the end we want an implementation that works under Stacked Borrow rules -- even if they are not perfect -- because that's what is currently available to check things. |
Hi! I implemented all mutable cases (using transmutes) except case 4. I also added I didn't manage to implement case 4. If implemented using transmutes, it complains that the sizes of If implemented using a Uninit array, we basically get into the same issue, that there's no easy stable interface for assuming that a generic array is initialized (mentioned in the same link; also see tracking issue for unstable solution. There is a workaround, but it's more complicated and uses more unsafe primitives. I left the attempted implementation of case 4 (using MaybeUninit like you suggested) in comments in the code so that you could try it. I also ran into an issue of not being able to call the same Also, a random thought: do you think the function should always return I guess I will indeed focus on the mutable case only. |
Hi, Sorry, I've been a bit rushed so I haven't had time to review the code; I'll get to that later this week hopefully.
It's a bit sad that case 4 cannot be implemented, but having 4 out of 5 is better than none; we can always add 4 later.
Hopefully fixable; I'll have a look when I review. Otherwise not as bad indeed.
That's an interesting question. I think it's better for generic functions to have a generic interface in general; after all, the generic functions are only called in generic context, so a divergent interface in those cases is just created more troubles for the caller. In this specific case, however, this raises the possibility of using The interface remains generic for those who want to handle the generic case, complete with an error type to use, however the specific infallible implementations can use a Never Type (aka Furthermore, users can check for the presence of infallible borrow by constraining the error type: As a result, I think this is the best of both worlds:
|
Hi, I review the code and it all looks good to me. Is there anything more you'd like to do? If not I'll go ahead and merge it, then iterate on it to non-mutable / mutable-unchecked methods, etc... |
No, I think that's pretty much it. :) |
Thank you very much for your contribution. |
This adds functionality for getting multiple borrows from different ghostcells at the same time.
I put this under an experimental flag, since it seems that this wasn't proven by the ghostcell paper. However, qcell
seems to already have this functionality for some time, and it definitely sounds sound to me.
In any case, this probably needs a macro, or some other way, to mutably borrow more than 3 elements at a time, and we can't write a method for each number.