diff --git a/src/librustc/traits/specialize/specialization_graph.rs b/src/librustc/traits/specialize/specialization_graph.rs index e237cab5ea135..e44e1453b7965 100644 --- a/src/librustc/traits/specialize/specialization_graph.rs +++ b/src/librustc/traits/specialize/specialization_graph.rs @@ -366,7 +366,7 @@ impl<'a, 'gcx, 'tcx> Node { pub fn items( &self, tcx: TyCtxt<'a, 'gcx, 'tcx>, - ) -> impl Iterator + 'a { + ) -> ty::AssociatedItemsIterator<'a, 'gcx, 'tcx> { tcx.associated_items(self.def_id()) } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index ef9b3e3efab27..9a63bb374c66d 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -2674,10 +2674,17 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn associated_items( self, def_id: DefId, - ) -> impl Iterator + 'a { - let def_ids = self.associated_item_def_ids(def_id); - Box::new((0..def_ids.len()).map(move |i| self.associated_item(def_ids[i]))) - as Box + 'a> + ) -> AssociatedItemsIterator<'a, 'gcx, 'tcx> { + // Ideally, we would use `-> impl Iterator` here, but it falls + // afoul of the conservative "capture [restrictions]" we put + // in place, so we use a hand-written iterator. + // + // [restrictions]: https://github.com/rust-lang/rust/issues/34511#issuecomment-373423999 + AssociatedItemsIterator { + tcx: self, + def_ids: self.associated_item_def_ids(def_id), + next_index: 0, + } } /// Returns `true` if the impls are the same polarity and the trait either @@ -2874,6 +2881,22 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } +pub struct AssociatedItemsIterator<'a, 'gcx: 'tcx, 'tcx: 'a> { + tcx: TyCtxt<'a, 'gcx, 'tcx>, + def_ids: Lrc>, + next_index: usize, +} + +impl Iterator for AssociatedItemsIterator<'_, '_, '_> { + type Item = AssociatedItem; + + fn next(&mut self) -> Option { + let def_id = self.def_ids.get(self.next_index)?; + self.next_index += 1; + Some(self.tcx.associated_item(*def_id)) + } +} + impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn with_freevars(self, fid: NodeId, f: F) -> T where F: FnOnce(&[hir::Freevar]) -> T,