Skip to content

Commit 70cbccc

Browse files
committed
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 0d97c1a + e6e5635 commit 70cbccc

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;
@@ -1346,49 +1345,88 @@ impl<'tcx> ToPredicate<'tcx> for PolyProjectionPredicate<'tcx> {
13461345
}
13471346
}
13481347

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

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

0 commit comments

Comments
 (0)