[nll] change how MIR represents places#53247
[nll] change how MIR represents places#53247csmoe wants to merge 33 commits intorust-lang:masterfrom
Conversation
|
cc @eddyb as well |
src/librustc/ich/impls_mir.rs
Outdated
| hasher: &mut StableHasher<W>, | ||
| ) { | ||
| self.base.hash_stable(hcx, hasher); | ||
| self.elems.hash_stable(hcx, hasher); |
There was a problem hiding this comment.
You might be able to use one of the macros since this is just a struct now.
| impl<'a, 'tcx> Place<'tcx> { | ||
| // projection lives in the last elem. | ||
| pub fn projection(&self) -> Option<&PlaceElem> { | ||
| self.elems.last() |
There was a problem hiding this comment.
IMO such a method is a hazard. All users should iterate over the elems vector.
There was a problem hiding this comment.
I'm not sure I agree with "hazard", but I think a name like last_projection would be good. Also, can the return type be Option<&'tcx PlaceElem>?
There was a problem hiding this comment.
This looks like a hazard to me as well. Better naming would help here, but I don’t see any reason against just inspecting the slice in-place.
src/librustc/mir/mod.rs
Outdated
| ) -> Self { | ||
| Place { | ||
| base: self.base, | ||
| elems: tcx.intern_place_elems(&[elem]), |
There was a problem hiding this comment.
This replaces the current elems - it should instead have elem at the end.
There was a problem hiding this comment.
Minor nit.
The builder pattern used here suggests that the Place should be built up incrementally, but it seems to me that it would unnecessarily intern every single intermediate projection. That is, the code currently does not expose any way to construct the whole projection in one go, so one would end up doing something along the lines of
let place = Place::local(x);
let place = place.such_projection(...);
let place = place.another_projection(...);
...
and thus having every slice for each intermediate projection interned. Not sure if this is a relevant problem or whether the current code would be able to take advantage of a one-shot method, though.
| ProjectionElem::Subslice { from, to } => { | ||
| write!(fmt, "{:?}[{:?}:-{:?}]", data.base, from, to) | ||
| } | ||
| }, |
There was a problem hiding this comment.
You need to move this in a custom Debug impl for Place.
src/librustc/mir/mod.rs
Outdated
| @@ -1731,7 +1737,7 @@ pub struct Projection<'tcx, B, V, T> { | |||
| pub elem: ProjectionElem<'tcx, V, T>, | |||
| } | |||
There was a problem hiding this comment.
The Projection struct should be removed.
| // | ||
| // Place: base.[] | ||
| // ^^-- no projection | ||
| // ^^^^-- PlaceTy |
There was a problem hiding this comment.
This is inaccurate, it's only applying .c but you also have .a and .b to apply before.
src/librustc/mir/tcx.rs
Outdated
| // if no projection returns the place itself, | ||
| // Base.[] => Base.[] | ||
| // ^^-- no projection | ||
| pub fn base_place<'cx, 'gcx>( |
There was a problem hiding this comment.
Probably a bad idea, because of inefficiency - you should be able to rewrite all the algorithms to work on [PlaceElem] instead of the recursive data structure.
|
@csmoe It seems that there needs to be a bit more work put into avoiding looking at only the last projection element (previously recursive algorithms should now be iterative). |
| match place.base { | ||
| PlaceBase::Promoted(_) | ||
| | PlaceBase::Static(..) => false, | ||
| PlaceBase::Local(..) => true, |
There was a problem hiding this comment.
@eddyb there are plenty of such pattern-matchs on old_place, I'm a bit uncertain this translation, is this correct?
There was a problem hiding this comment.
borrow_of_local_data is a recursive function, which means you can make it iterate over the elems.
Furthermore, in this case specifically, if you made it iterative, you'd notice that the elems don't change at all whether the function returns true or false, it just needs to look at the base.
src/librustc/mir/mod.rs
Outdated
|
|
||
| pub fn downcast(self, adt_def: &'tcx AdtDef, variant_index: usize) -> Place<'tcx> { | ||
| self.elem(ProjectionElem::Downcast(adt_def, variant_index)) | ||
| pub fn deref(self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Self { |
There was a problem hiding this comment.
I think this should be tcx: TyCtxt<'_, '_, 'tcx>
src/librustc/mir/mod.rs
Outdated
| Place::Projection(Box::new(PlaceProjection { base: self, elem })) | ||
| pub fn elem( | ||
| self, | ||
| tcx: TyCtxt<'a, 'tcx, 'tcx>, |
ed44737 to
2dc5b86
Compare
| } else { | ||
| false | ||
| }, | ||
| "Unexpected capture place", |
There was a problem hiding this comment.
I'm currently getting a failure here, and I think it's because this code is not really equivalent to the old code. I think this is where a split_projection sort of thing would be useful. In any case, the problem here I believe:
If you have something like *x.f -- this has a tree structure like:
- deref
- field (
f)- base:
x
- base:
- field (
but in the code here we will pull off the last projection (*) and then look at arg_place.base, which is x, ignoring the field f that comes in between.
nikomatsakis
left a comment
There was a problem hiding this comment.
So, this seems right, though as I wrote -- I would avoid the massive closure and instead have a proper fn.
| }) | ||
| }) | ||
| } | ||
| let place_elements_conflict = |tcx: TyCtxt<'_, 'gcx, 'tcx>, |
There was a problem hiding this comment.
So, stylistically, I would prefer to keep this as a separate function. I really dislike large closures -- it's hard to distinguish what state they access from the surrounding environment.
| // potentially stopping at non-operand projections, | ||
| // which would trigger `not_ssa` on locals. | ||
| self.visit_place(&proj.base, context, location); | ||
| return; |
There was a problem hiding this comment.
@nikomatsakis how can I rewrite this self-recursive block in iteration? I suspect my continue rewriting is very incorrect.
|
closing as this PR appears to have been superseded by PR #54426 |
#Closes #52708
r? @nikomatsakis