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 upRemoving RefCells and Cells from FunctionContext in trans #25332
Conversation
pythonesque
added some commits
May 11, 2015
rust-highfive
assigned
nrc
May 12, 2015
This comment has been minimized.
This comment has been minimized.
|
r? @nrc (rust_highfive has picked a reviewer for you, use r? to override) |
This comment has been minimized.
This comment has been minimized.
|
If |
This comment has been minimized.
This comment has been minimized.
Since one of them is mutable, the pair would move every time, so we'd lose the function pointer unless we carefully threaded it back through every return value (I believe, anyway). We could work around that by constructing a fresh pair each time, but then you're really not gaining anything compared to just passing two parameters. I did consider trying it anyway though.
Yeah, like I commented in the other PR, I think that in this case it may have been better to just get rid of
Making everything a method on |
pythonesque
referenced this pull request
May 12, 2015
Closed
Get rid of most of the RefCells in librustc_typeck/check #25247
This comment has been minimized.
This comment has been minimized.
Well, your wish came true. A few months ago, actually :). As for creating a fresh pair every time, you could use a |
This comment has been minimized.
This comment has been minimized.
|
...Whoa, how did I miss that? Okay then, that makes the method solution a lot more attractive.
Doesn't reborrowing only occur if the function takes a reference in the first place (in which case you wouldn't be passing by value)? Or am I misunderstanding what you're saying? |
This comment has been minimized.
This comment has been minimized.
|
@pythonesque Yes, but you can reproduce the semantics of reborrowing with a method that takes |
This comment has been minimized.
This comment has been minimized.
|
|
This comment has been minimized.
This comment has been minimized.
|
@pythonesque do you intend to move some of these functions to methods on Block? Should I hold back on reviewing until then? I don't mind passing |
This comment has been minimized.
This comment has been minimized.
|
@nrc I actually started doing switching over to making everything methods on |
nrc
reviewed
May 20, 2015
| fn trans<'r, 'blk>(&self, | ||
| &mut Block { bl, ref mut fcx }: &mut Block<'r, 'blk, 'tcx>) | ||
| -> OptResult<'blk> { | ||
| let mut bcx = &mut bl.with(fcx); |
This comment has been minimized.
This comment has been minimized.
nrc
May 20, 2015
Member
This is a bit weird - especially to newcomers to trans - we take a Block as parameter, then create a new one, using only the components of the passed Block, then later in the function we use the fields of the same Block again. Either with needs a better name indicating what is going on, or we need a comment here.
This comment has been minimized.
This comment has been minimized.
pythonesque
May 20, 2015
Author
Contributor
This pattern (well, similar) was actually already used all over the place prior to this PR. But I'll take a closer look at this particular one.
I could rename it to with_fcx, if that helps. Note that the reason we do this is to reborrow it; otherwise borrowck yells at me really, really hard.
nrc
reviewed
May 20, 2015
| { | ||
| //let Block { bl, ref mut fcx } = *bcx; |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
nrc
reviewed
May 20, 2015
| @@ -547,7 +552,7 @@ impl<'a, 'tcx> FunctionContext<'a, 'tcx> { | |||
| // code. Each basic block we generate is attached to a function, typically | |||
| // with many basic blocks per function. All the basic blocks attached to a | |||
| // function are organized as a directed graph. | |||
| pub struct BlockS<'blk, 'tcx: 'blk> { | |||
| pub struct BlockS { | |||
This comment has been minimized.
This comment has been minimized.
nrc
May 20, 2015
Member
It's pretty bad that we export both Block and BlockS types from this module. Previously we only used Block and it was a typedef. If we need to use both publicly, then we should change BlockS to have a more descriptive name - BlockGraph or BlockSet or something.
This comment has been minimized.
This comment has been minimized.
pythonesque
May 20, 2015
Author
Contributor
I think we may not need it to be public, actually. I'll double check.
Oh wait, from the module. Yeah, I'll rename it.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
pythonesque
May 20, 2015
Author
Contributor
@eddyb Yeah, I figured... perhaps something like BlockData would be better? Or, rename it to Block and call the thing we're passing around everywhere BlockContext or something (we even call it bcx everywhere).
nrc
reviewed
May 20, 2015
|
|
||
| // The function context for the function to which this block is | ||
| // attached. | ||
| pub fcx: &'r mut FunctionContext<'blk, 'tcx>, |
This comment has been minimized.
This comment has been minimized.
nrc
May 20, 2015
Member
Since every block in a BlockS is in the same function, why do they each need their own reference to a function context? Seems like leaving it in BlockS is better?
This comment has been minimized.
This comment has been minimized.
pythonesque
May 20, 2015
Author
Contributor
BlockS is the one that's being allocated in the arena (which is what we were doing before) which stored an extra fcx each time, which didn't make sense (IMO). Block is really just a temporary structure useful for passing along a function context and block reference. As you can see, the fcx is &mut, and we nearly always have a &mut Block, so we never really have more than one at a time anyway.
This comment has been minimized.
This comment has been minimized.
|
Wow, that is quite a PR! So, I think it makes sense and I'm in favour of landing. It certainly seems like a win in terms of perf. It still seems a bit messier than I would like (the design of Block, some how, rather than the quality of the code or anything like that), but it doesn't seem that there is a great solution under it all. I'd be keen to know what the Block + methods approach looks like, but I'd be happy to see this land. r=me with the Block/BlockS and with naming issue addressed, unless the inherant impl thing works out. |
pythonesque
added some commits
May 20, 2015
This comment has been minimized.
This comment has been minimized.
|
@nrc Addressed your comments and synced to latest master. |
This comment has been minimized.
This comment has been minimized.
|
Maybe we can refactor terminated: Cell<bool>,
unreachable: Cell<bool>,
/// Is this block part of a landing pad?
is_lpad: bool,
/// AST node-id associated with this block, if any. Used debugging purposes only.
opt_node_id: Option<ast::NodeId>,
Verdict: we should be able to pass around only the |
This comment has been minimized.
This comment has been minimized.
|
@eddyb Yes, I also was wondering about the arena. I think I eventually concluded that the references are held onto somewhere in the drop glue code and that trying to refactor that as well was something I could look at after the initial version landed. I'm not 100% sure that all those fields are just caches of the LLVM ones; I would have to look into it. Either way, it seems to me that so long as we're relying on the information living in LLVM, we would still need some sort of lifetime attached (even if only as I think I agree that you could get away with not having an explicit lifetime for the In general: I agree there is lots of refactoring work we can do on top of this change, but I think it will be much easier to figure out what we can and can't get away with after we are passing around |
This comment has been minimized.
This comment has been minimized.
|
|
This comment has been minimized.
This comment has been minimized.
|
|
This comment has been minimized.
This comment has been minimized.
|
I started a discuss thread to discuss this approach, since it seems to have some pros and cons: https://internals.rust-lang.org/t/prs-removing-refcells-longer-term-plans/2099 |
This comment has been minimized.
This comment has been minimized.
|
|
This comment has been minimized.
This comment has been minimized.
|
Closing due to inactivity, but feel free to reopen with a rebase! |
pythonesque commentedMay 12, 2015
The
FunctionContextis now passed around mutably pretty much everywhere.The
RefCellmotherlode in trans is in the local crate context, but I think this part can stand on its own. I did check to see if I could make the local crate context mutable really easily, but after a few tests I think it would require enough additional work that it probably isn't worth delaying this PR submission.