Skip to content

Commit bfd3833

Browse files
authored
Rollup merge of rust-lang#55949 - ljedrz:return_impl_Iterator_from_Predicate_walk_tys, r=oli-obk
ty: return impl Iterator from Predicate::walk_tys Fixes the lazyboye `FIXME` by returning a custom `Iterator` as intended by the original author of the function. It is indeed a bit convoluted, so I'm ok with not changing this if perf results are not favourable enough. Also happy to adjust any names if need be.
2 parents 6aa1e5f + e6e5635 commit bfd3833

File tree

1 file changed

+58
-20
lines changed

1 file changed

+58
-20
lines changed

src/librustc/ty/mod.rs

+58-20
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ use std::hash::{Hash, Hasher};
4949
use std::ops::Deref;
5050
use rustc_data_structures::sync::{self, Lrc, ParallelIterator, par_iter};
5151
use std::slice;
52-
use std::vec::IntoIter;
5352
use std::{mem, ptr};
5453
use syntax::ast::{self, DUMMY_NODE_ID, Name, Ident, NodeId};
5554
use syntax::attr;
@@ -1343,49 +1342,88 @@ impl<'tcx> ToPredicate<'tcx> for PolyProjectionPredicate<'tcx> {
13431342
}
13441343
}
13451344

1345+
// A custom iterator used by Predicate::walk_tys.
1346+
enum WalkTysIter<'tcx, I, J, K>
1347+
where I: Iterator<Item = Ty<'tcx>>,
1348+
J: Iterator<Item = Ty<'tcx>>,
1349+
K: Iterator<Item = Ty<'tcx>>
1350+
{
1351+
None,
1352+
One(Ty<'tcx>),
1353+
Two(Ty<'tcx>, Ty<'tcx>),
1354+
Types(I),
1355+
InputTypes(J),
1356+
ProjectionTypes(K)
1357+
}
1358+
1359+
impl<'tcx, I, J, K> Iterator for WalkTysIter<'tcx, I, J, K>
1360+
where I: Iterator<Item = Ty<'tcx>>,
1361+
J: Iterator<Item = Ty<'tcx>>,
1362+
K: Iterator<Item = Ty<'tcx>>
1363+
{
1364+
type Item = Ty<'tcx>;
1365+
1366+
fn next(&mut self) -> Option<Ty<'tcx>> {
1367+
match *self {
1368+
WalkTysIter::None => None,
1369+
WalkTysIter::One(item) => {
1370+
*self = WalkTysIter::None;
1371+
Some(item)
1372+
},
1373+
WalkTysIter::Two(item1, item2) => {
1374+
*self = WalkTysIter::One(item2);
1375+
Some(item1)
1376+
},
1377+
WalkTysIter::Types(ref mut iter) => {
1378+
iter.next()
1379+
},
1380+
WalkTysIter::InputTypes(ref mut iter) => {
1381+
iter.next()
1382+
},
1383+
WalkTysIter::ProjectionTypes(ref mut iter) => {
1384+
iter.next()
1385+
}
1386+
}
1387+
}
1388+
}
1389+
13461390
impl<'tcx> Predicate<'tcx> {
13471391
/// Iterates over the types in this predicate. Note that in all
13481392
/// cases this is skipping over a binder, so late-bound regions
13491393
/// with depth 0 are bound by the predicate.
1350-
pub fn walk_tys(&self) -> IntoIter<Ty<'tcx>> {
1351-
let vec: Vec<_> = match *self {
1394+
pub fn walk_tys(&'a self) -> impl Iterator<Item = Ty<'tcx>> + 'a {
1395+
match *self {
13521396
ty::Predicate::Trait(ref data) => {
1353-
data.skip_binder().input_types().collect()
1397+
WalkTysIter::InputTypes(data.skip_binder().input_types())
13541398
}
13551399
ty::Predicate::Subtype(binder) => {
13561400
let SubtypePredicate { a, b, a_is_expected: _ } = binder.skip_binder();
1357-
vec![a, b]
1401+
WalkTysIter::Two(a, b)
13581402
}
13591403
ty::Predicate::TypeOutlives(binder) => {
1360-
vec![binder.skip_binder().0]
1404+
WalkTysIter::One(binder.skip_binder().0)
13611405
}
13621406
ty::Predicate::RegionOutlives(..) => {
1363-
vec![]
1407+
WalkTysIter::None
13641408
}
13651409
ty::Predicate::Projection(ref data) => {
13661410
let inner = data.skip_binder();
1367-
inner.projection_ty.substs.types().chain(Some(inner.ty)).collect()
1411+
WalkTysIter::ProjectionTypes(
1412+
inner.projection_ty.substs.types().chain(Some(inner.ty)))
13681413
}
13691414
ty::Predicate::WellFormed(data) => {
1370-
vec![data]
1415+
WalkTysIter::One(data)
13711416
}
13721417
ty::Predicate::ObjectSafe(_trait_def_id) => {
1373-
vec![]
1418+
WalkTysIter::None
13741419
}
13751420
ty::Predicate::ClosureKind(_closure_def_id, closure_substs, _kind) => {
1376-
closure_substs.substs.types().collect()
1421+
WalkTysIter::Types(closure_substs.substs.types())
13771422
}
13781423
ty::Predicate::ConstEvaluatable(_, substs) => {
1379-
substs.types().collect()
1424+
WalkTysIter::Types(substs.types())
13801425
}
1381-
};
1382-
1383-
// FIXME: The only reason to collect into a vector here is that I was
1384-
// too lazy to make the full (somewhat complicated) iterator
1385-
// type that would be needed here. But I wanted this fn to
1386-
// return an iterator conceptually, rather than a `Vec`, so as
1387-
// to be closer to `Ty::walk`.
1388-
vec.into_iter()
1426+
}
13891427
}
13901428

13911429
pub fn to_opt_poly_trait_ref(&self) -> Option<PolyTraitRef<'tcx>> {

0 commit comments

Comments
 (0)