@@ -319,12 +319,58 @@ fn process_predicate<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
319319 FulfillmentErrorCode < ' tcx > >
320320{
321321 match process_predicate1 ( selcx, pending_obligation, backtrace, region_obligations) {
322- Ok ( Some ( v) ) => Ok ( Some ( v. into_iter ( )
323- . map ( |o| PendingPredicateObligation {
324- obligation : o,
325- stalled_on : vec ! [ ]
326- } )
327- . collect ( ) ) ) ,
322+ Ok ( Some ( v) ) => {
323+ // FIXME the right thing to do here, I think, is to permit
324+ // DAGs. That is, we should detect whenever this predicate
325+ // has appeared somewhere in the current tree./ If it's a
326+ // parent, that's a cycle, and we should either error out
327+ // or consider it ok. But if it's NOT a parent, we can
328+ // ignore it, since it will be proven (or not) separately.
329+ // However, this is a touch tricky, so I'm doing something
330+ // a bit hackier for now so that the `huge-struct.rs` passes.
331+
332+ let retain_vec: Vec < _ > = {
333+ let mut dedup = FnvHashSet ( ) ;
334+ v. iter ( )
335+ . map ( |o| {
336+ // Screen out obligations that we know globally
337+ // are true. This should really be the DAG check
338+ // mentioned above.
339+ if
340+ o. predicate . is_global ( ) &&
341+ selcx. tcx ( ) . fulfilled_predicates . borrow ( ) . is_duplicate ( & o. predicate )
342+ {
343+ return false ;
344+ }
345+
346+ // If we see two siblings that are exactly the
347+ // same, no need to add them twice.
348+ if !dedup. insert ( & o. predicate ) {
349+ return false ;
350+ }
351+
352+ true
353+ } )
354+ . collect ( )
355+ } ;
356+
357+ let pending_predicate_obligations =
358+ v. into_iter ( )
359+ . zip ( retain_vec)
360+ . flat_map ( |( o, retain) | {
361+ if retain {
362+ Some ( PendingPredicateObligation {
363+ obligation : o,
364+ stalled_on : vec ! [ ]
365+ } )
366+ } else {
367+ None
368+ }
369+ } )
370+ . collect ( ) ;
371+
372+ Ok ( Some ( pending_predicate_obligations) )
373+ }
328374 Ok ( None ) => Ok ( None ) ,
329375 Err ( e) => Err ( e)
330376 }
0 commit comments