]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_infer/traits/util.rs
fix elaborate for predicates with unbound variables
[rust.git] / src / librustc_infer / traits / util.rs
index 4ae7e417a8f673d017da6ca897d3cebe910a7eec..6aeb225a6e9cbf7a789274bf6d495b6367dac3dc 100644 (file)
@@ -3,7 +3,7 @@
 use crate::traits::{Obligation, ObligationCause, PredicateObligation};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_middle::ty::outlives::Component;
-use rustc_middle::ty::{self, ToPolyTraitRef, ToPredicate, TyCtxt, WithConstness};
+use rustc_middle::ty::{self, ToPredicate, TyCtxt, WithConstness};
 use rustc_span::Span;
 
 pub fn anonymize_predicate<'tcx>(
@@ -12,21 +12,16 @@ pub fn anonymize_predicate<'tcx>(
 ) -> ty::Predicate<'tcx> {
     let kind = pred.kind();
     let new = match kind {
-        &ty::PredicateKind::Trait(ref data, constness) => {
-            ty::PredicateKind::Trait(tcx.anonymize_late_bound_regions(data), constness)
+        ty::PredicateKind::ForAll(binder) => {
+            ty::PredicateKind::ForAll(tcx.anonymize_late_bound_regions(binder))
         }
+        &ty::PredicateKind::Trait(data, constness) => ty::PredicateKind::Trait(data, constness),
 
-        ty::PredicateKind::RegionOutlives(data) => {
-            ty::PredicateKind::RegionOutlives(tcx.anonymize_late_bound_regions(data))
-        }
+        &ty::PredicateKind::RegionOutlives(data) => ty::PredicateKind::RegionOutlives(data),
 
-        ty::PredicateKind::TypeOutlives(data) => {
-            ty::PredicateKind::TypeOutlives(tcx.anonymize_late_bound_regions(data))
-        }
+        &ty::PredicateKind::TypeOutlives(data) => ty::PredicateKind::TypeOutlives(data),
 
-        ty::PredicateKind::Projection(data) => {
-            ty::PredicateKind::Projection(tcx.anonymize_late_bound_regions(data))
-        }
+        &ty::PredicateKind::Projection(data) => ty::PredicateKind::Projection(data),
 
         &ty::PredicateKind::WellFormed(data) => ty::PredicateKind::WellFormed(data),
 
@@ -36,15 +31,13 @@ pub fn anonymize_predicate<'tcx>(
             ty::PredicateKind::ClosureKind(closure_def_id, closure_substs, kind)
         }
 
-        ty::PredicateKind::Subtype(data) => {
-            ty::PredicateKind::Subtype(tcx.anonymize_late_bound_regions(data))
-        }
+        &ty::PredicateKind::Subtype(data) => ty::PredicateKind::Subtype(data),
 
         &ty::PredicateKind::ConstEvaluatable(def_id, substs) => {
             ty::PredicateKind::ConstEvaluatable(def_id, substs)
         }
 
-        ty::PredicateKind::ConstEquate(c1, c2) => ty::PredicateKind::ConstEquate(c1, c2),
+        &ty::PredicateKind::ConstEquate(c1, c2) => ty::PredicateKind::ConstEquate(c1, c2),
     };
 
     if new != *kind { new.to_predicate(tcx) } else { pred }
@@ -152,21 +145,25 @@ fn predicate_obligation<'tcx>(
 }
 
 impl Elaborator<'tcx> {
-    pub fn filter_to_traits(self) -> FilterToTraits<Self> {
-        FilterToTraits::new(self)
+    pub fn filter_to_traits(self) -> FilterToTraits<'tcx, Self> {
+        FilterToTraits::new(self.visited.tcx, self)
     }
 
     fn elaborate(&mut self, obligation: &PredicateObligation<'tcx>) {
         let tcx = self.visited.tcx;
-        match obligation.predicate.kind() {
-            ty::PredicateKind::Trait(ref data, _) => {
+
+        match obligation.predicate.ignore_qualifiers(tcx).skip_binder().kind() {
+            ty::PredicateKind::ForAll(_) => {
+                bug!("unexpected predicate: {:?}", obligation.predicate)
+            }
+            ty::PredicateKind::Trait(data, _) => {
                 // Get predicates declared on the trait.
                 let predicates = tcx.super_predicates_of(data.def_id());
 
-                let obligations = predicates.predicates.iter().map(|(pred, span)| {
+                let obligations = predicates.predicates.iter().map(|&(pred, span)| {
                     predicate_obligation(
-                        pred.subst_supertrait(tcx, &data.to_poly_trait_ref()),
-                        Some(*span),
+                        pred.subst_supertrait(tcx, &ty::Binder::bind(data.trait_ref)),
+                        Some(span),
                     )
                 });
                 debug!("super_predicates: data={:?}", data);
@@ -209,7 +206,7 @@ fn elaborate(&mut self, obligation: &PredicateObligation<'tcx>) {
             ty::PredicateKind::RegionOutlives(..) => {
                 // Nothing to elaborate from `'a: 'b`.
             }
-            ty::PredicateKind::TypeOutlives(ref data) => {
+            ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty_max, r_min)) => {
                 // We know that `T: 'a` for some type `T`. We can
                 // often elaborate this. For example, if we know that
                 // `[U]: 'a`, that implies that `U: 'a`. Similarly, if
@@ -224,8 +221,6 @@ fn elaborate(&mut self, obligation: &PredicateObligation<'tcx>) {
                 // consider this as evidence that `T: 'static`, but
                 // I'm a bit wary of such constructions and so for now
                 // I want to be conservative. --nmatsakis
-                let ty_max = data.skip_binder().0;
-                let r_min = data.skip_binder().1;
                 if r_min.is_late_bound() {
                     return;
                 }
@@ -241,16 +236,16 @@ fn elaborate(&mut self, obligation: &PredicateObligation<'tcx>) {
                                 if r.is_late_bound() {
                                     None
                                 } else {
-                                    Some(ty::PredicateKind::RegionOutlives(ty::Binder::dummy(
-                                        ty::OutlivesPredicate(r, r_min),
+                                    Some(ty::PredicateKind::RegionOutlives(ty::OutlivesPredicate(
+                                        r, r_min,
                                     )))
                                 }
                             }
 
                             Component::Param(p) => {
                                 let ty = tcx.mk_ty_param(p.index, p.name);
-                                Some(ty::PredicateKind::TypeOutlives(ty::Binder::dummy(
-                                    ty::OutlivesPredicate(ty, r_min),
+                                Some(ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(
+                                    ty, r_min,
                                 )))
                             }
 
@@ -294,7 +289,7 @@ fn next(&mut self) -> Option<Self::Item> {
 // Supertrait iterator
 ///////////////////////////////////////////////////////////////////////////
 
-pub type Supertraits<'tcx> = FilterToTraits<Elaborator<'tcx>>;
+pub type Supertraits<'tcx> = FilterToTraits<'tcx, Elaborator<'tcx>>;
 
 pub fn supertraits<'tcx>(
     tcx: TyCtxt<'tcx>,
@@ -316,23 +311,24 @@ pub fn transitive_bounds<'tcx>(
 
 /// A filter around an iterator of predicates that makes it yield up
 /// just trait references.
-pub struct FilterToTraits<I> {
+pub struct FilterToTraits<'tcx, I> {
+    tcx: TyCtxt<'tcx>,
     base_iterator: I,
 }
 
-impl<I> FilterToTraits<I> {
-    fn new(base: I) -> FilterToTraits<I> {
-        FilterToTraits { base_iterator: base }
+impl<'tcx, I> FilterToTraits<'tcx, I> {
+    fn new(tcx: TyCtxt<'tcx>, base: I) -> FilterToTraits<'tcx, I> {
+        FilterToTraits { tcx, base_iterator: base }
     }
 }
 
-impl<'tcx, I: Iterator<Item = PredicateObligation<'tcx>>> Iterator for FilterToTraits<I> {
+impl<'tcx, I: Iterator<Item = PredicateObligation<'tcx>>> Iterator for FilterToTraits<'tcx, I> {
     type Item = ty::PolyTraitRef<'tcx>;
 
     fn next(&mut self) -> Option<ty::PolyTraitRef<'tcx>> {
         while let Some(obligation) = self.base_iterator.next() {
-            if let ty::PredicateKind::Trait(data, _) = obligation.predicate.kind() {
-                return Some(data.to_poly_trait_ref());
+            if let Some(data) = obligation.predicate.to_opt_poly_trait_ref(self.tcx) {
+                return Some(data);
             }
         }
         None