about summary refs log tree commit diff
diff options
context:
space:
mode:
authorscalexm <alexandre@scalexm.fr>2018-11-23 19:16:02 +0100
committerscalexm <alexandre@scalexm.fr>2018-12-27 19:21:15 +0100
commit9b87f590dcefc619c3d1e080062cc7bb2e0fb5fb (patch)
tree78487068bd8bd5f1d264a30b13595350ab26c933
parentf2b92174e3c25e54156efcbdc105a48d50afb6be (diff)
downloadrust-9b87f590dcefc619c3d1e080062cc7bb2e0fb5fb.tar.gz
rust-9b87f590dcefc619c3d1e080062cc7bb2e0fb5fb.zip
Implement `is_coinductive`
Fixes #55096.
-rw-r--r--src/librustc_traits/chalk_context/mod.rs23
1 files changed, 20 insertions, 3 deletions
diff --git a/src/librustc_traits/chalk_context/mod.rs b/src/librustc_traits/chalk_context/mod.rs
index 4f6ad83f2e6..41b7e73e553 100644
--- a/src/librustc_traits/chalk_context/mod.rs
+++ b/src/librustc_traits/chalk_context/mod.rs
@@ -155,12 +155,29 @@ impl context::AggregateOps<ChalkArenas<'gcx>> for ChalkContext<'cx, 'gcx> {
 }
 
 impl context::ContextOps<ChalkArenas<'gcx>> for ChalkContext<'cx, 'gcx> {
-    /// True if this is a coinductive goal -- e.g., proving an auto trait.
+    /// True if this is a coinductive goal: basically proving that an auto trait
+    /// is implemented or proving that a trait reference is well-formed.
     fn is_coinductive(
         &self,
-        _goal: &Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>
+        goal: &Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>
     ) -> bool {
-        unimplemented!()
+        use rustc::traits::{WellFormed, WhereClause};
+
+        let mut goal = goal.value.goal;
+        loop {
+            match goal {
+                GoalKind::DomainGoal(domain_goal) => match domain_goal {
+                    DomainGoal::WellFormed(WellFormed::Trait(..)) => return true,
+                    DomainGoal::Holds(WhereClause::Implemented(trait_predicate)) => {
+                        return self.tcx.trait_is_auto(trait_predicate.def_id());
+                    }
+                    _ => return false,
+                }
+
+                GoalKind::Quantified(_, bound_goal) => goal = *bound_goal.skip_binder(),
+                _ => return false,
+            }
+        }
     }
 
     /// Create an inference table for processing a new goal and instantiate that goal