Stream: t-compiler/help

Topic: unroll_place questions


Santiago Pastorino (Feb 27 2019 at 18:43, on Zulip):

I have a couple of questions related to unroll_place

Santiago Pastorino (Feb 27 2019 at 18:44, on Zulip):

I was starting to talk with @nikomatsakis about this, but I figure that's better for a separate topic

Santiago Pastorino (Feb 27 2019 at 18:45, on Zulip):

first, PlaceComponentIter is not really an iterator

Santiago Pastorino (Feb 27 2019 at 18:45, on Zulip):

I can live with it

Santiago Pastorino (Feb 27 2019 at 18:45, on Zulip):

was just wondering

Santiago Pastorino (Feb 27 2019 at 18:45, on Zulip):

https://github.com/rust-lang/rust/blob/ea43c3c688980edd6f09a4cb632c9eb996c4f2af/src/librustc_mir/borrow_check/places_conflict.rs#L304-L309

Santiago Pastorino (Feb 27 2019 at 18:46, on Zulip):

I wonder, when and why do you want to keep executing when you get None?

Santiago Pastorino (Feb 27 2019 at 18:46, on Zulip):

and why you can't do that with an real iterator

Santiago Pastorino (Feb 27 2019 at 18:48, on Zulip):

I guess you can but you would allow the usage of for x in iter and that's not what you want given that you want to do something even when the thing returns None and with for syntax you won't be in the loop anymore if it returns None? I guess that's what the text is referring to?

nikomatsakis (Feb 27 2019 at 18:48, on Zulip):

ah

nikomatsakis (Feb 27 2019 at 18:48, on Zulip):

well, you can do that with a real iterator

nikomatsakis (Feb 27 2019 at 18:48, on Zulip):

in general, the Iterator trait does not guarantee what happens once None is returned

nikomatsakis (Feb 27 2019 at 18:49, on Zulip):

but for any given iterator, you may have guarantees

nikomatsakis (Feb 27 2019 at 18:49, on Zulip):

(and in particular, you can invoke fuse to get an iterator that is guaranteed to be a no-op, if needed -- it wouldn't be here)

nikomatsakis (Feb 27 2019 at 18:49, on Zulip):

but in any case

Santiago Pastorino (Feb 27 2019 at 18:49, on Zulip):

in general, the Iterator trait does not guarantee what happens once None is returned

ahh ok, I was assuming that it keeps returning None, could even panic I guess but checking that has perf implications

nikomatsakis (Feb 27 2019 at 18:50, on Zulip):

I think that this code is the case we want to keep going

nikomatsakis (Feb 27 2019 at 18:50, on Zulip):

i.e., if you borrowed x but accessed *x.y

Santiago Pastorino (Feb 27 2019 at 18:51, on Zulip):

ahh ok

Santiago Pastorino (Feb 27 2019 at 18:51, on Zulip):

so unroll is not really a general purpose thing to iterate over Place

Santiago Pastorino (Feb 27 2019 at 18:51, on Zulip):

it's just a convenience for the conflicts thing

nikomatsakis (Feb 27 2019 at 18:51, on Zulip):

then the returns would be something like:

nikomatsakis (Feb 27 2019 at 18:52, on Zulip):

anyway I forget exactly but in some cases I guess that may turn out ok, in others not

nikomatsakis (Feb 27 2019 at 18:52, on Zulip):

so unroll is not really a general purpose thing to iterate over Place

well, yes and no

nikomatsakis (Feb 27 2019 at 18:52, on Zulip):

I mean it was not meant for "general use"

nikomatsakis (Feb 27 2019 at 18:52, on Zulip):

but really it does just let you iterate

Santiago Pastorino (Feb 27 2019 at 18:52, on Zulip):

yep

nikomatsakis (Feb 27 2019 at 18:52, on Zulip):

so it could be used generally

Santiago Pastorino (Feb 27 2019 at 18:52, on Zulip):

but I probably prefer something else

Santiago Pastorino (Feb 27 2019 at 18:52, on Zulip):

well I guess it depends

Santiago Pastorino (Feb 27 2019 at 18:52, on Zulip):

anyway, let me go to the next question :)

nikomatsakis (Feb 27 2019 at 18:52, on Zulip):

but the conflict checking really does want to ensure that None keeps getting returned

nikomatsakis (Feb 27 2019 at 18:53, on Zulip):

(you can certainly achieve that constraint)

Santiago Pastorino (Feb 27 2019 at 18:54, on Zulip):

so, all this is motivated by using unroll as an iterate method for Place and then keep moving to Place 2.0

Santiago Pastorino (Feb 27 2019 at 18:55, on Zulip):

thing is ... look at how it looks like the code for fn ty using unroll

Santiago Pastorino (Feb 27 2019 at 18:55, on Zulip):
157     pub fn ty<'a, 'gcx, D>(&self, local_decls: &D, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> PlaceTy<'tcx>
158         where D: HasLocalDecls<'tcx>
159     {
160         self.unroll(None, |mut place_components| {
161             let base = place_components.next().unwrap();
162             let mut place_ty = match *base {
163                 Place::Base(PlaceBase::Local(index)) =>
164                     PlaceTy::Ty { ty: local_decls.local_decls()[index].ty },
165                 Place::Base(PlaceBase::Promoted(ref data)) => PlaceTy::Ty { ty: data.1 },
166                 Place::Base(PlaceBase::Static(ref data)) =>
167                     PlaceTy::Ty { ty: data.ty },
168                 Place::Projection(_) =>
169                     bug!("This should be a base place"),
170             };
171
172             // apply .projection_ty() to all elems but only returns the final one.
173             while let Some(elem) = place_components.next() {
174                 match elem {
175                     Place::Base(_) =>
176                         bug!("This should be a projection place"),
177                     Place::Projection(ref proj) =>
178                         place_ty = place_ty.projection_ty(tcx, &proj.elem),
179                 }
180             }
181
182             place_ty
183         })
184     }
Santiago Pastorino (Feb 27 2019 at 18:56, on Zulip):

that's why I meant, that I'd prefer having an iterator that returns projections only

Santiago Pastorino (Feb 27 2019 at 18:56, on Zulip):

so first I ask for base

Santiago Pastorino (Feb 27 2019 at 18:56, on Zulip):

and then I iterate

Santiago Pastorino (Feb 27 2019 at 18:56, on Zulip):

like in

Santiago Pastorino (Feb 27 2019 at 18:56, on Zulip):
    pub fn ty<'a, 'gcx>(
        &self,
        local_decls: &impl HasLocalDecls<'tcx>,
        tcx: TyCtxt<'a, 'gcx, 'tcx>,
    ) -> PlaceTy<'tcx> {
        let mut place_ty = PlaceTy::from(self.base.ty(local_decls));

        // apply .projection_ty() to all elems but only returns the final one.
        for elem in self.elems.iter() {
            place_ty = place_ty.projection_ty(tcx, elem);
        }

        place_ty
    }
Santiago Pastorino (Feb 27 2019 at 19:01, on Zulip):

I can have a base and projection methods, they probably already exist, but still ...

nikomatsakis (Feb 27 2019 at 19:06, on Zulip):

I see

nikomatsakis (Feb 27 2019 at 19:06, on Zulip):

It seems fairly straightforward to adapt unroll_place in this way, @Santiago Pastorino

nikomatsakis (Feb 27 2019 at 19:07, on Zulip):

and of course if you had such an iterator

nikomatsakis (Feb 27 2019 at 19:07, on Zulip):

you could trivially use it to reproduce the existing unroll_place interface

nikomatsakis (Feb 27 2019 at 19:07, on Zulip):

e.g., I believe I saw something about getting a callback like (base, projections_iter)

Santiago Pastorino (Feb 27 2019 at 19:07, on Zulip):

you mean, having unroll_place returning a struct that gives you base and elems in different fields

Santiago Pastorino (Feb 27 2019 at 19:07, on Zulip):

something like that

Santiago Pastorino (Feb 27 2019 at 19:07, on Zulip):

it may worth playing with it I guess

nikomatsakis (Feb 27 2019 at 19:08, on Zulip):

in which case we could do Some(Place::Base(base)).chain(projections_iter.map(PlaceProjection)) or something like that

nikomatsakis (Feb 27 2019 at 19:08, on Zulip):

you mean, having unroll_place returning a struct that gives you base and elems in different fields

the document had an API in which you got a callback with two arguments

nikomatsakis (Feb 27 2019 at 19:08, on Zulip):

in contrast to the unroll_place API, which calls you back with one (unified) iterator

nikomatsakis (Feb 27 2019 at 19:09, on Zulip):

in any case either seems fine

Santiago Pastorino (Feb 27 2019 at 19:54, on Zulip):

you mean, having unroll_place returning a struct that gives you base and elems in different fields

the document had an API in which you got a callback with two arguments

btw, which document?

nikomatsakis (Feb 27 2019 at 20:50, on Zulip):

@Santiago Pastorino I meant the dropbox paper from the all hands

Santiago Pastorino (Feb 27 2019 at 20:57, on Zulip):

ahh the one from the all hands

oli (Feb 28 2019 at 07:52, on Zulip):

This is partially why I wanted to have Place be a struct with the base field and a projection-tree field. Many place uses only care about the base, or care about it first and then about the other projections

Jake Goulding (Mar 11 2019 at 20:54, on Zulip):

(and in particular, you can invoke fuse to get an iterator that is guaranteed to be a no-op, if needed -- it wouldn't be here)

FWIW, it's better to always call .fuse() if you need the behavior, and implement FusedIterator for your iterator if it will always return None after the first.

Last update: Nov 11 2019 at 22:55UTC