]> git.lizzy.rs Git - rust.git/commitdiff
Implement a hacky version of the DAG support we ultimately want, leaving
authorNiko Matsakis <niko@alum.mit.edu>
Mon, 11 Jan 2016 20:49:30 +0000 (15:49 -0500)
committerNiko Matsakis <niko@alum.mit.edu>
Sat, 16 Jan 2016 10:22:33 +0000 (05:22 -0500)
a FIXME for later.

src/librustc/middle/traits/fulfill.rs
src/test/compile-fail/issue-20831-debruijn.rs
src/test/compile-fail/recursion.rs

index 2fdf93e6e35dea903d0da0d50639d1d22f551382..7d1af8ca83aa02285f6153863f5c277504f3bc7b 100644 (file)
@@ -319,12 +319,58 @@ fn process_predicate<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
                                         FulfillmentErrorCode<'tcx>>
 {
     match process_predicate1(selcx, pending_obligation, backtrace, region_obligations) {
-        Ok(Some(v)) => Ok(Some(v.into_iter()
-                                .map(|o| PendingPredicateObligation {
-                                    obligation: o,
-                                    stalled_on: vec![]
-                                })
-                               .collect())),
+        Ok(Some(v)) => {
+            // FIXME the right thing to do here, I think, is to permit
+            // DAGs. That is, we should detect whenever this predicate
+            // has appeared somewhere in the current tree./ If it's a
+            // parent, that's a cycle, and we should either error out
+            // or consider it ok. But if it's NOT a parent, we can
+            // ignore it, since it will be proven (or not) separately.
+            // However, this is a touch tricky, so I'm doing something
+            // a bit hackier for now so that the `huge-struct.rs` passes.
+
+            let retain_vec: Vec<_> = {
+                let mut dedup = FnvHashSet();
+                v.iter()
+                 .map(|o| {
+                     // Screen out obligations that we know globally
+                     // are true. This should really be the DAG check
+                     // mentioned above.
+                     if
+                         o.predicate.is_global() &&
+                         selcx.tcx().fulfilled_predicates.borrow().is_duplicate(&o.predicate)
+                     {
+                         return false;
+                     }
+
+                     // If we see two siblings that are exactly the
+                     // same, no need to add them twice.
+                     if !dedup.insert(&o.predicate) {
+                         return false;
+                     }
+
+                     true
+                 })
+                 .collect()
+            };
+
+            let pending_predicate_obligations =
+                v.into_iter()
+                 .zip(retain_vec)
+                 .flat_map(|(o, retain)| {
+                     if retain {
+                         Some(PendingPredicateObligation {
+                             obligation: o,
+                             stalled_on: vec![]
+                         })
+                     } else {
+                         None
+                     }
+                 })
+                .collect();
+
+            Ok(Some(pending_predicate_obligations))
+        }
         Ok(None) => Ok(None),
         Err(e) => Err(e)
     }
index 48ea344c7c24caa3a45f11fcdc6447ed5c9fcb91..3f96a9c342283d0678db124b5d7bfe0e4ca200bc 100644 (file)
@@ -40,7 +40,6 @@ fn subscribe(&mut self, t : Box<Subscriber<Input=<Self as Publisher>::Output> +
         //~^^ ERROR cannot infer
         //~|  ERROR cannot infer
         //~|  ERROR cannot infer
-        //~|  ERROR cannot infer
         //
         // The fact that `Publisher` is using an implicit lifetime is
         // what was causing the debruijn accounting to be off, so
index b1d45a82276a8b3c39bae308870f96d2a8ba1449..3221ae4629643a68ffa2c2ebee619bf11117ce17 100644 (file)
@@ -19,8 +19,8 @@ fn dot(&self, other:Cons<T>) -> isize {
     self.head * other.head + self.tail.dot(other.tail)
   }
 }
-fn test<T:Dot> (n:isize, i:isize, first:T, second:T) ->isize {
-  match n {    0 => {first.dot(second)} //~ ERROR overflow
+fn test<T:Dot> (n:isize, i:isize, first:T, second:T) ->isize { //~ ERROR recursion limit
+  match n {    0 => {first.dot(second)}
       // FIXME(#4287) Error message should be here. It should be
       // a type error to instantiate `test` at a type other than T.
     _ => {test (n-1, i+1, Cons {head:2*i+1, tail:first}, Cons{head:i*i, tail:second})}