Skip to content

Commit 57c31b2

Browse files
committed
Implement a hacky version of the DAG support we ultimately want, leaving
a FIXME for later.
1 parent 3046ac2 commit 57c31b2

File tree

3 files changed

+54
-9
lines changed

3 files changed

+54
-9
lines changed

src/librustc/middle/traits/fulfill.rs

+52-6
Original file line numberDiff line numberDiff line change
@@ -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
}

src/test/compile-fail/issue-20831-debruijn.rs

-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ impl<'a> Publisher<'a> for MyStruct<'a> {
4040
//~^^ ERROR cannot infer
4141
//~| ERROR cannot infer
4242
//~| ERROR cannot infer
43-
//~| ERROR cannot infer
4443
//
4544
// The fact that `Publisher` is using an implicit lifetime is
4645
// what was causing the debruijn accounting to be off, so

src/test/compile-fail/recursion.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ impl<T:Dot> Dot for Cons<T> {
1919
self.head * other.head + self.tail.dot(other.tail)
2020
}
2121
}
22-
fn test<T:Dot> (n:isize, i:isize, first:T, second:T) ->isize {
23-
match n { 0 => {first.dot(second)} //~ ERROR overflow
22+
fn test<T:Dot> (n:isize, i:isize, first:T, second:T) ->isize { //~ ERROR recursion limit
23+
match n { 0 => {first.dot(second)}
2424
// FIXME(#4287) Error message should be here. It should be
2525
// a type error to instantiate `test` at a type other than T.
2626
_ => {test (n-1, i+1, Cons {head:2*i+1, tail:first}, Cons{head:i*i, tail:second})}

0 commit comments

Comments
 (0)