|
8 | 8 | // option. This file may not be copied, modified, or distributed |
9 | 9 | // except according to those terms. |
10 | 10 |
|
| 11 | +use smallvec::SmallVec; |
| 12 | + |
11 | 13 | use hir::{self}; |
12 | 14 | use hir::def_id::DefId; |
13 | 15 | use syntax_pos::Span; |
@@ -282,63 +284,79 @@ pub struct TraitRefExpander<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { |
282 | 284 |
|
283 | 285 | #[derive(Debug, Clone)] |
284 | 286 | pub struct TraitRefExpansionInfo<'tcx> { |
285 | | - pub top_level_trait_ref: ty::PolyTraitRef<'tcx>, |
286 | | - pub top_level_span: Span, |
287 | | - pub trait_ref: ty::PolyTraitRef<'tcx>, |
288 | | - pub span: Span, |
| 287 | + pub items: SmallVec<[(ty::PolyTraitRef<'tcx>, Span); 4]>, |
| 288 | +} |
| 289 | + |
| 290 | +impl<'tcx> TraitRefExpansionInfo<'tcx> { |
| 291 | + fn new(trait_ref: ty::PolyTraitRef<'tcx>, span: Span) -> TraitRefExpansionInfo<'tcx> { |
| 292 | + TraitRefExpansionInfo { |
| 293 | + items: smallvec![(trait_ref, span)] |
| 294 | + } |
| 295 | + } |
| 296 | + |
| 297 | + fn push(&self, trait_ref: ty::PolyTraitRef<'tcx>, span: Span) -> TraitRefExpansionInfo<'tcx> { |
| 298 | + let mut items = self.items.clone(); |
| 299 | + items.push((trait_ref, span)); |
| 300 | + |
| 301 | + TraitRefExpansionInfo { |
| 302 | + items |
| 303 | + } |
| 304 | + } |
| 305 | + |
| 306 | + pub fn trait_ref(&self) -> &ty::PolyTraitRef<'tcx> { |
| 307 | + &self.top().0 |
| 308 | + } |
| 309 | + |
| 310 | + pub fn top(&self) -> &(ty::PolyTraitRef<'tcx>, Span) { |
| 311 | + self.items.last().unwrap() |
| 312 | + } |
| 313 | + |
| 314 | + pub fn bottom(&self) -> &(ty::PolyTraitRef<'tcx>, Span) { |
| 315 | + self.items.first().unwrap() |
| 316 | + } |
289 | 317 | } |
290 | 318 |
|
291 | 319 | pub fn expand_trait_refs<'cx, 'gcx, 'tcx>( |
292 | 320 | tcx: TyCtxt<'cx, 'gcx, 'tcx>, |
293 | 321 | trait_refs: impl IntoIterator<Item = (ty::PolyTraitRef<'tcx>, Span)> |
294 | 322 | ) -> TraitRefExpander<'cx, 'gcx, 'tcx> { |
295 | 323 | let mut visited = PredicateSet::new(tcx); |
296 | | - let mut items: Vec<_> = |
297 | | - trait_refs.into_iter() |
298 | | - .map(|(tr, sp)| TraitRefExpansionInfo { |
299 | | - top_level_trait_ref: tr.clone(), |
300 | | - top_level_span: sp, |
301 | | - trait_ref: tr, |
302 | | - span: sp, |
303 | | - }) |
| 324 | + let mut items: Vec<_> = trait_refs |
| 325 | + .into_iter() |
| 326 | + .map(|(tr, sp)| TraitRefExpansionInfo::new(tr, sp)) |
304 | 327 | .collect(); |
305 | | - items.retain(|item| visited.insert(&item.trait_ref.to_predicate())); |
| 328 | + items.retain(|i| visited.insert(&i.trait_ref().to_predicate())); |
306 | 329 | TraitRefExpander { stack: items, visited: visited, } |
307 | 330 | } |
308 | 331 |
|
309 | 332 | impl<'cx, 'gcx, 'tcx> TraitRefExpander<'cx, 'gcx, 'tcx> { |
310 | 333 | // Returns `true` if `item` refers to a trait. |
311 | 334 | fn push(&mut self, item: &TraitRefExpansionInfo<'tcx>) -> bool { |
312 | 335 | let tcx = self.visited.tcx; |
| 336 | + let trait_ref = item.trait_ref(); |
313 | 337 |
|
314 | | - if !ty::is_trait_alias(tcx, item.trait_ref.def_id()) { |
| 338 | + if !ty::is_trait_alias(tcx, trait_ref.def_id()) { |
315 | 339 | return true; |
316 | 340 | } |
317 | 341 |
|
318 | 342 | // Get predicates declared on the trait. |
319 | | - let predicates = tcx.super_predicates_of(item.trait_ref.def_id()); |
| 343 | + let predicates = tcx.super_predicates_of(trait_ref.def_id()); |
320 | 344 |
|
321 | 345 | let mut items: Vec<_> = predicates.predicates |
322 | 346 | .iter() |
323 | 347 | .rev() |
324 | 348 | .filter_map(|(pred, sp)| { |
325 | | - pred.subst_supertrait(tcx, &item.trait_ref) |
| 349 | + pred.subst_supertrait(tcx, &trait_ref) |
326 | 350 | .to_opt_poly_trait_ref() |
327 | | - .map(|trait_ref| |
328 | | - TraitRefExpansionInfo { |
329 | | - trait_ref, |
330 | | - span: *sp, |
331 | | - ..*item |
332 | | - } |
333 | | - ) |
| 351 | + .map(|tr| item.push(tr, *sp)) |
334 | 352 | }) |
335 | 353 | .collect(); |
336 | 354 |
|
337 | 355 | debug!("expand_trait_refs: trait_ref={:?} items={:?}", |
338 | | - item.trait_ref, items); |
| 356 | + trait_ref, items); |
339 | 357 |
|
340 | 358 | // Only keep those items that we haven't already seen. |
341 | | - items.retain(|i| self.visited.insert(&i.trait_ref.to_predicate())); |
| 359 | + items.retain(|i| self.visited.insert(&i.trait_ref().to_predicate())); |
342 | 360 |
|
343 | 361 | self.stack.extend(items); |
344 | 362 | false |
|
0 commit comments