]> git.lizzy.rs Git - rust.git/commitdiff
add Subtype predicate
authorNiko Matsakis <niko@alum.mit.edu>
Fri, 10 Mar 2017 02:47:09 +0000 (21:47 -0500)
committerNiko Matsakis <niko@alum.mit.edu>
Wed, 12 Apr 2017 00:32:46 +0000 (20:32 -0400)
17 files changed:
src/librustc/ich/impls_ty.rs
src/librustc/infer/mod.rs
src/librustc/middle/free_region.rs
src/librustc/traits/error_reporting.rs
src/librustc/traits/fulfill.rs
src/librustc/traits/object_safety.rs
src/librustc/traits/select.rs
src/librustc/traits/structural_impls.rs
src/librustc/traits/util.rs
src/librustc/ty/mod.rs
src/librustc/ty/structural_impls.rs
src/librustc/ty/util.rs
src/librustc/ty/wf.rs
src/librustc/util/ppaux.rs
src/librustc_typeck/check/closure.rs
src/librustc_typeck/check/method/probe.rs
src/librustdoc/clean/mod.rs

index 7b6f3af2a11ec88582d572128185e17c029b4a43..b8888eee9c6efb4218ac9a1379eeb97817957fcb 100644 (file)
@@ -170,6 +170,7 @@ fn hash_stable<W: StableHasherResult>(&self,
 impl_stable_hash_for!(struct ty::TraitRef<'tcx> { def_id, substs });
 impl_stable_hash_for!(struct ty::TraitPredicate<'tcx> { trait_ref });
 impl_stable_hash_for!(tuple_struct ty::EquatePredicate<'tcx> { t1, t2 });
+impl_stable_hash_for!(struct ty::SubtypePredicate<'tcx> { a_is_expected, a, b });
 
 impl<'a, 'tcx, A, B> HashStable<StableHashingContext<'a, 'tcx>> for ty::OutlivesPredicate<A, B>
     where A: HashStable<StableHashingContext<'a, 'tcx>>,
@@ -200,6 +201,9 @@ fn hash_stable<W: StableHasherResult>(&self,
             ty::Predicate::Equate(ref pred) => {
                 pred.hash_stable(hcx, hasher);
             }
+            ty::Predicate::Subtype(ref pred) => {
+                pred.hash_stable(hcx, hasher);
+            }
             ty::Predicate::RegionOutlives(ref pred) => {
                 pred.hash_stable(hcx, hasher);
             }
index 98c8ce0f031440524e0094baa50ca5a0f92dcfe4..999ebbfa20fbf8f62a540bd0687696da73594032 100644 (file)
@@ -551,7 +551,7 @@ pub fn enter<F, R>(&'tcx mut self, f: F) -> R
 }
 
 impl<T> ExpectedFound<T> {
-    fn new(a_is_expected: bool, a: T, b: T) -> Self {
+    pub fn new(a_is_expected: bool, a: T, b: T) -> Self {
         if a_is_expected {
             ExpectedFound {expected: a, found: b}
         } else {
@@ -1129,6 +1129,43 @@ pub fn equality_predicate(&self,
         })
     }
 
+    pub fn subtype_predicate(&self,
+                             cause: &ObligationCause<'tcx>,
+                             predicate: &ty::PolySubtypePredicate<'tcx>)
+        -> Option<InferResult<'tcx, ()>>
+    {
+        // Subtle: it's ok to skip the binder here and resolve because
+        // `shallow_resolve` just ignores anything that is not a type
+        // variable, and because type variable's can't (at present, at
+        // least) capture any of the things bound by this binder.
+        //
+        // Really, there is no *particular* reason to do this
+        // `shallow_resolve` here except as a
+        // micro-optimization. Naturally I could not
+        // resist. -nmatsakis
+        let two_unbound_type_vars = {
+            let a = self.shallow_resolve(predicate.skip_binder().a);
+            let b = self.shallow_resolve(predicate.skip_binder().b);
+            a.is_ty_var() && b.is_ty_var()
+        };
+
+        if two_unbound_type_vars {
+            // Two unbound type variables? Can't make progress.
+            return None;
+        }
+
+        Some(self.commit_if_ok(|snapshot| {
+            let (ty::SubtypePredicate { a_is_expected, a, b}, skol_map) =
+                self.skolemize_late_bound_regions(predicate, snapshot);
+
+            let cause_span = cause.span;
+            let ok = self.sub_types(a_is_expected, cause, a, b)?;
+            self.leak_check(false, cause_span, &skol_map, snapshot)?;
+            self.pop_skolemized(skol_map, snapshot);
+            Ok(ok.unit())
+        }))
+    }
+
     pub fn region_outlives_predicate(&self,
                                      cause: &traits::ObligationCause<'tcx>,
                                      predicate: &ty::PolyRegionOutlivesPredicate<'tcx>)
index cdb081ab40098655ab325fec2aa5bc29a0c2a3d2..963cc4314eda544789399753325b038102d7d7bc 100644 (file)
@@ -60,6 +60,7 @@ pub fn relate_free_regions_from_predicates(&mut self,
                 ty::Predicate::Projection(..) |
                 ty::Predicate::Trait(..) |
                 ty::Predicate::Equate(..) |
+                ty::Predicate::Subtype(..) |
                 ty::Predicate::WellFormed(..) |
                 ty::Predicate::ObjectSafe(..) |
                 ty::Predicate::ClosureKind(..) |
index 931c77badad222009ee0e6da53af98e99d2b5ee1..8a303a5da1184263b4ea847df1b8795d83b95d6d 100644 (file)
@@ -39,6 +39,7 @@
 use ty::fast_reject;
 use ty::fold::TypeFolder;
 use ty::subst::Subst;
+use ty::SubtypePredicate;
 use util::nodemap::{FxHashMap, FxHashSet};
 
 use syntax_pos::{DUMMY_SP, Span};
@@ -112,6 +113,13 @@ fn report_fulfillment_error(&self,
             FulfillmentErrorCode::CodeAmbiguity => {
                 self.maybe_report_ambiguity(&error.obligation);
             }
+            FulfillmentErrorCode::CodeSubtypeError(ref expected_found, ref err) => {
+                self.report_mismatched_types(&error.obligation.cause,
+                                             expected_found.expected,
+                                             expected_found.found,
+                                             err.clone())
+                    .emit();
+            }
         }
     }
 
@@ -555,6 +563,11 @@ pub fn report_selection_error(&self,
                         err
                     }
 
+                    ty::Predicate::Subtype(ref predicate) => {
+                        // TODO
+                        panic!("subtype requirement not satisfied {:?}", predicate)
+                    }
+
                     ty::Predicate::Equate(ref predicate) => {
                         let predicate = self.resolve_type_vars_if_possible(predicate);
                         let err = self.equality_predicate(&obligation.cause,
@@ -761,6 +774,16 @@ fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>) {
                 }
             }
 
+            ty::Predicate::Subtype(ref data) => {
+                if data.references_error() || self.tcx.sess.has_errors() {
+                    // no need to overload user in such cases
+                } else {
+                    let &SubtypePredicate { a_is_expected: _, a, b } = data.skip_binder();
+                    assert!(a.is_ty_var() && b.is_ty_var()); // else other would've been instantiated
+                    self.need_type_info(obligation, a);
+                }
+            }
+
             _ => {
                 if !self.tcx.sess.has_errors() {
                     let mut err = struct_span_err!(self.tcx.sess,
index b87d18464377f6b3f4481210de7eb09651fff63b..64453f2983b92f03b6a86ae8444f2474630a052c 100644 (file)
@@ -11,6 +11,7 @@
 use dep_graph::DepGraph;
 use infer::{InferCtxt, InferOk};
 use ty::{self, Ty, TypeFoldable, ToPolyTraitRef, TyCtxt, ToPredicate};
+use ty::error::ExpectedFound;
 use rustc_data_structures::obligation_forest::{ObligationForest, Error};
 use rustc_data_structures::obligation_forest::{ForestObligation, ObligationProcessor};
 use std::marker::PhantomData;
@@ -496,6 +497,26 @@ fn process_predicate<'a, 'gcx, 'tcx>(
                 s => Ok(s)
             }
         }
+
+        ty::Predicate::Subtype(ref subtype) => {
+            match selcx.infcx().subtype_predicate(&obligation.cause, subtype) {
+                None => {
+                    // none means that both are unresolved
+                    pending_obligation.stalled_on = vec![subtype.skip_binder().a,
+                                                         subtype.skip_binder().b];
+                    Ok(None)
+                }
+                Some(Ok(ok)) => {
+                    Ok(Some(ok.obligations))
+                }
+                Some(Err(err)) => {
+                    let expected_found = ExpectedFound::new(subtype.skip_binder().a_is_expected,
+                                                            subtype.skip_binder().a,
+                                                            subtype.skip_binder().b);
+                    Err(FulfillmentErrorCode::CodeSubtypeError(expected_found, err))
+                }
+            }
+        }
     }
 }
 
index 7cd0b26940d9118284e3adcc03b35a3fda36972d..d190635bec3063ce3c0e8193fba6cde6942e0800 100644 (file)
@@ -178,6 +178,7 @@ fn predicates_reference_self(
                     ty::Predicate::TypeOutlives(..) |
                     ty::Predicate::RegionOutlives(..) |
                     ty::Predicate::ClosureKind(..) |
+                    ty::Predicate::Subtype(..) |
                     ty::Predicate::Equate(..) => {
                         false
                     }
@@ -209,6 +210,7 @@ fn generics_require_sized_self(self, def_id: DefId) -> bool {
                     ty::Predicate::Projection(..) |
                     ty::Predicate::Trait(..) |
                     ty::Predicate::Equate(..) |
+                    ty::Predicate::Subtype(..) |
                     ty::Predicate::RegionOutlives(..) |
                     ty::Predicate::WellFormed(..) |
                     ty::Predicate::ObjectSafe(..) |
index 38ea1e4a19b91f536e989da9610cc1547384e700..67d50210ba39adb94a909c475424607ba445f5d4 100644 (file)
@@ -568,6 +568,18 @@ fn evaluate_predicate_recursively<'o>(&mut self,
                 }
             }
 
+            ty::Predicate::Subtype(ref p) => {
+                // does this code ever run?
+                match self.infcx.subtype_predicate(&obligation.cause, p) {
+                    Some(Ok(InferOk { obligations, .. })) => {
+                        self.inferred_obligations.extend(obligations);
+                        EvaluatedToOk
+                    },
+                    Some(Err(_)) => EvaluatedToErr,
+                    None => EvaluatedToAmbig,
+                }
+            }
+
             ty::Predicate::WellFormed(ty) => {
                 match ty::wf::obligations(self.infcx, obligation.cause.body_id,
                                           ty, obligation.cause.span) {
index 44ef461327ddbf868837dd5b2b00559a3af4528e..fcaa29be9632c21d1f56e78c8630a95edc2fba77 100644 (file)
@@ -130,6 +130,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
             super::CodeSelectionError(ref e) => write!(f, "{:?}", e),
             super::CodeProjectionError(ref e) => write!(f, "{:?}", e),
+            super::CodeSubtypeError(ref a, ref b) => write!(f, "CodeSubtypeError({:?}, {:?})", a, b),
             super::CodeAmbiguity => write!(f, "Ambiguity")
         }
     }
index 602f27a64d4d8d195b14c2903e4cfe6b2ac06f78..d4245ec9b2475aa79fa033e16a1de9d874bd5ff8 100644 (file)
@@ -42,7 +42,10 @@ fn anonymize_predicate<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
             ty::Predicate::ObjectSafe(data),
 
         ty::Predicate::ClosureKind(closure_def_id, kind) =>
-            ty::Predicate::ClosureKind(closure_def_id, kind)
+            ty::Predicate::ClosureKind(closure_def_id, kind),
+
+        ty::Predicate::Subtype(ref data) =>
+            ty::Predicate::Subtype(tcx.anonymize_late_bound_regions(data)),
     }
 }
 
@@ -160,6 +163,10 @@ fn push(&mut self, predicate: &ty::Predicate<'tcx>) {
                 // `X == Y`, though conceivably we might. For example,
                 // `&X == &Y` implies that `X == Y`.
             }
+            ty::Predicate::Subtype(..) => {
+                // Currently, we do not "elaborate" predicates like `X
+                // <: Y`, though conceivably we might.
+            }
             ty::Predicate::Projection(..) => {
                 // Nothing to elaborate in a projection predicate.
             }
index 292e30e3d41f19403353bfdd2a055ac4c1066daf..d720911db39fbb4196739d16e462aa931aad28d7 100644 (file)
@@ -755,6 +755,9 @@ pub enum Predicate<'tcx> {
     /// for some substitutions `...` and T being a closure type.
     /// Satisfied (or refuted) once we know the closure's kind.
     ClosureKind(DefId, ClosureKind),
+
+    /// `T1 <: T2`
+    Subtype(PolySubtypePredicate<'tcx>),
 }
 
 impl<'a, 'gcx, 'tcx> Predicate<'tcx> {
@@ -833,6 +836,8 @@ pub fn subst_supertrait(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
                 Predicate::Trait(ty::Binder(data.subst(tcx, substs))),
             Predicate::Equate(ty::Binder(ref data)) =>
                 Predicate::Equate(ty::Binder(data.subst(tcx, substs))),
+            Predicate::Subtype(ty::Binder(ref data)) =>
+                Predicate::Subtype(ty::Binder(data.subst(tcx, substs))),
             Predicate::RegionOutlives(ty::Binder(ref data)) =>
                 Predicate::RegionOutlives(ty::Binder(data.subst(tcx, substs))),
             Predicate::TypeOutlives(ty::Binder(ref data)) =>
@@ -912,6 +917,14 @@ pub fn dep_node(&self) -> DepNode<DefId> {
                                                                    &'tcx ty::Region>;
 pub type PolyTypeOutlivesPredicate<'tcx> = PolyOutlivesPredicate<Ty<'tcx>, &'tcx ty::Region>;
 
+#[derive(Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
+pub struct SubtypePredicate<'tcx> {
+    pub a_is_expected: bool,
+    pub a: Ty<'tcx>,
+    pub b: Ty<'tcx>
+}
+pub type PolySubtypePredicate<'tcx> = ty::Binder<SubtypePredicate<'tcx>>;
+
 /// This kind of predicate has no *direct* correspondent in the
 /// syntax, but it roughly corresponds to the syntactic forms:
 ///
@@ -1025,6 +1038,9 @@ pub fn walk_tys(&self) -> IntoIter<Ty<'tcx>> {
             ty::Predicate::Equate(ty::Binder(ref data)) => {
                 vec![data.0, data.1]
             }
+            ty::Predicate::Subtype(ty::Binder(SubtypePredicate { a, b, a_is_expected: _ })) => {
+                vec![a, b]
+            }
             ty::Predicate::TypeOutlives(ty::Binder(ref data)) => {
                 vec![data.0]
             }
@@ -1061,6 +1077,7 @@ pub fn to_opt_poly_trait_ref(&self) -> Option<PolyTraitRef<'tcx>> {
             }
             Predicate::Projection(..) |
             Predicate::Equate(..) |
+            Predicate::Subtype(..) |
             Predicate::RegionOutlives(..) |
             Predicate::WellFormed(..) |
             Predicate::ObjectSafe(..) |
index 9126600e3f65393d2eff900e06bcbd077535be8d..a4466d7d840110f450a7b4e8e959164da13402c3 100644 (file)
@@ -111,6 +111,18 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>)
     }
 }
 
+impl<'a, 'tcx> Lift<'tcx> for ty::SubtypePredicate<'a> {
+    type Lifted = ty::SubtypePredicate<'tcx>;
+    fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>)
+                             -> Option<ty::SubtypePredicate<'tcx>> {
+        tcx.lift(&(self.a, self.b)).map(|(a, b)| ty::SubtypePredicate {
+            a_is_expected: self.a_is_expected,
+            a: a,
+            b: b,
+        })
+    }
+}
+
 impl<'tcx, A: Copy+Lift<'tcx>, B: Copy+Lift<'tcx>> Lift<'tcx> for ty::OutlivesPredicate<A, B> {
     type Lifted = ty::OutlivesPredicate<A::Lifted, B::Lifted>;
     fn lift_to_tcx<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Option<Self::Lifted> {
@@ -167,6 +179,9 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lif
             ty::Predicate::Equate(ref binder) => {
                 tcx.lift(binder).map(ty::Predicate::Equate)
             }
+            ty::Predicate::Subtype(ref binder) => {
+                tcx.lift(binder).map(ty::Predicate::Subtype)
+            }
             ty::Predicate::RegionOutlives(ref binder) => {
                 tcx.lift(binder).map(ty::Predicate::RegionOutlives)
             }
@@ -693,6 +708,8 @@ fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F)
                 ty::Predicate::Trait(a.fold_with(folder)),
             ty::Predicate::Equate(ref binder) =>
                 ty::Predicate::Equate(binder.fold_with(folder)),
+            ty::Predicate::Subtype(ref binder) =>
+                ty::Predicate::Subtype(binder.fold_with(folder)),
             ty::Predicate::RegionOutlives(ref binder) =>
                 ty::Predicate::RegionOutlives(binder.fold_with(folder)),
             ty::Predicate::TypeOutlives(ref binder) =>
@@ -712,6 +729,7 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
         match *self {
             ty::Predicate::Trait(ref a) => a.visit_with(visitor),
             ty::Predicate::Equate(ref binder) => binder.visit_with(visitor),
+            ty::Predicate::Subtype(ref binder) => binder.visit_with(visitor),
             ty::Predicate::RegionOutlives(ref binder) => binder.visit_with(visitor),
             ty::Predicate::TypeOutlives(ref binder) => binder.visit_with(visitor),
             ty::Predicate::Projection(ref binder) => binder.visit_with(visitor),
@@ -776,8 +794,7 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
 
 impl<'tcx> TypeFoldable<'tcx> for ty::EquatePredicate<'tcx> {
     fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
-        ty::EquatePredicate(self.0.fold_with(folder),
-                            self.1.fold_with(folder))
+        ty::EquatePredicate(self.0.fold_with(folder), self.1.fold_with(folder))
     }
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
@@ -785,6 +802,20 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
     }
 }
 
+impl<'tcx> TypeFoldable<'tcx> for ty::SubtypePredicate<'tcx> {
+    fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
+        ty::SubtypePredicate {
+            a_is_expected: self.a_is_expected,
+            a: self.a.fold_with(folder),
+            b: self.b.fold_with(folder)
+        }
+    }
+
+    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
+        self.a.visit_with(visitor) || self.b.visit_with(visitor)
+    }
+}
+
 impl<'tcx> TypeFoldable<'tcx> for ty::TraitPredicate<'tcx> {
     fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
         ty::TraitPredicate {
index fd8191303a9a60cb92e9f1bb9bd1340daba448f5..2efefd750ae8a7ffd72ded7c8cd2deacf927aeac 100644 (file)
@@ -312,6 +312,7 @@ pub fn required_region_bounds(self,
                     ty::Predicate::Projection(..) |
                     ty::Predicate::Trait(..) |
                     ty::Predicate::Equate(..) |
+                    ty::Predicate::Subtype(..) |
                     ty::Predicate::WellFormed(..) |
                     ty::Predicate::ObjectSafe(..) |
                     ty::Predicate::ClosureKind(..) |
index 8a5bd6862cf4552c099b431fa344c81142dc7876..0b0e8a180cc36800c103ed87ead051ed584c8d0b 100644 (file)
@@ -94,6 +94,10 @@ pub fn predicate_obligations<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
         }
         ty::Predicate::ClosureKind(..) => {
         }
+        ty::Predicate::Subtype(ref data) => {
+            wf.compute(data.skip_binder().a); // (*)
+            wf.compute(data.skip_binder().b); // (*)
+        }
     }
 
     wf.normalize()
@@ -156,6 +160,7 @@ pub fn implied_bounds<'a, 'gcx, 'tcx>(
                 match obligation.predicate {
                     ty::Predicate::Trait(..) |
                     ty::Predicate::Equate(..) |
+                    ty::Predicate::Subtype(..) |
                     ty::Predicate::Projection(..) |
                     ty::Predicate::ClosureKind(..) |
                     ty::Predicate::ObjectSafe(..) =>
index 6323f1dc0d4c4a8da2f00a60797851a88b2edbe8..2daf71d95addf67c547871de9fb3e99a56475aea 100644 (file)
@@ -416,6 +416,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
             ty::Predicate::Trait(ref a) => write!(f, "{:?}", a),
             ty::Predicate::Equate(ref pair) => write!(f, "{:?}", pair),
+            ty::Predicate::Subtype(ref pair) => write!(f, "{:?}", pair),
             ty::Predicate::RegionOutlives(ref pair) => write!(f, "{:?}", pair),
             ty::Predicate::TypeOutlives(ref pair) => write!(f, "{:?}", pair),
             ty::Predicate::Projection(ref pair) => write!(f, "{:?}", pair),
@@ -676,6 +677,12 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
+impl<'tcx> fmt::Display for ty::Binder<ty::SubtypePredicate<'tcx>> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        ty::tls::with(|tcx| in_binder(f, tcx, self, tcx.lift(self)))
+    }
+}
+
 impl<'tcx> fmt::Display for ty::Binder<ty::ProjectionPredicate<'tcx>> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         ty::tls::with(|tcx| in_binder(f, tcx, self, tcx.lift(self)))
@@ -897,6 +904,12 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
+impl<'tcx> fmt::Display for ty::SubtypePredicate<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "{} <: {}", self.a, self.b)
+    }
+}
+
 impl<'tcx> fmt::Debug for ty::TraitPredicate<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f, "TraitPredicate({:?})",
@@ -949,6 +962,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
             ty::Predicate::Trait(ref data) => write!(f, "{}", data),
             ty::Predicate::Equate(ref predicate) => write!(f, "{}", predicate),
+            ty::Predicate::Subtype(ref predicate) => write!(f, "{}", predicate),
             ty::Predicate::RegionOutlives(ref predicate) => write!(f, "{}", predicate),
             ty::Predicate::TypeOutlives(ref predicate) => write!(f, "{}", predicate),
             ty::Predicate::Projection(ref predicate) => write!(f, "{}", predicate),
index 51fbc5aab6cd1510a87654b0f349967df668e050..78176b155691cef23cbc783376890d8837101c99 100644 (file)
@@ -169,6 +169,7 @@ fn deduce_expectations_from_obligations
                     ty::Predicate::Projection(ref data) => Some(data.to_poly_trait_ref()),
                     ty::Predicate::Trait(ref data) => Some(data.to_poly_trait_ref()),
                     ty::Predicate::Equate(..) => None,
+                    ty::Predicate::Subtype(..) => None,
                     ty::Predicate::RegionOutlives(..) => None,
                     ty::Predicate::TypeOutlives(..) => None,
                     ty::Predicate::WellFormed(..) => None,
index 5b0418921563a2dea56b4fa4bbf47897b57f3fc8..8071fe3cc2806a834f40ad273a059ad7f4b9d74d 100644 (file)
@@ -576,6 +576,7 @@ fn assemble_inherent_candidates_from_param(&mut self,
                         }
                     }
                     ty::Predicate::Equate(..) |
+                    ty::Predicate::Subtype(..) |
                     ty::Predicate::Projection(..) |
                     ty::Predicate::RegionOutlives(..) |
                     ty::Predicate::WellFormed(..) |
index ac72d7d29a24c4813839cd5b7185544ee269b698..1a194cd12546262e433d553ee15fd5229790b07b 100644 (file)
@@ -875,6 +875,7 @@ fn clean(&self, cx: &DocContext) -> WherePredicate {
         match *self {
             Predicate::Trait(ref pred) => pred.clean(cx),
             Predicate::Equate(ref pred) => pred.clean(cx),
+            Predicate::Subtype(ref pred) => pred.clean(cx),
             Predicate::RegionOutlives(ref pred) => pred.clean(cx),
             Predicate::TypeOutlives(ref pred) => pred.clean(cx),
             Predicate::Projection(ref pred) => pred.clean(cx),
@@ -904,6 +905,16 @@ fn clean(&self, cx: &DocContext) -> WherePredicate {
     }
 }
 
+impl<'tcx> Clean<WherePredicate> for ty::SubtypePredicate<'tcx> {
+    fn clean(&self, cx: &DocContext) -> WherePredicate {
+        let ty::SubtypePredicate { a_is_expected: _, a, b } = *self;
+        WherePredicate::EqPredicate { // TODO This is obviously wrong :P
+            lhs: a.clean(cx),
+            rhs: b.clean(cx)
+        }
+    }
+}
+
 impl<'tcx> Clean<WherePredicate> for ty::OutlivesPredicate<&'tcx ty::Region, &'tcx ty::Region> {
     fn clean(&self, cx: &DocContext) -> WherePredicate {
         let ty::OutlivesPredicate(ref a, ref b) = *self;