]> git.proxmox.com Git - rustc.git/blobdiff - src/librustc/traits/fulfill.rs
New upstream version 1.17.0+dfsg1
[rustc.git] / src / librustc / traits / fulfill.rs
index 23c28037a3c2d7b629f211c195446299032a6e0d..b87d18464377f6b3f4481210de7eb09651fff63b 100644 (file)
 use dep_graph::DepGraph;
 use infer::{InferCtxt, InferOk};
 use ty::{self, Ty, TypeFoldable, ToPolyTraitRef, TyCtxt, ToPredicate};
-use ty::subst::Subst;
 use rustc_data_structures::obligation_forest::{ObligationForest, Error};
 use rustc_data_structures::obligation_forest::{ForestObligation, ObligationProcessor};
 use std::marker::PhantomData;
-use std::mem;
 use syntax::ast;
 use util::nodemap::{FxHashSet, NodeMap};
 use hir::def_id::DefId;
@@ -23,9 +21,8 @@ use hir::def_id::DefId;
 use super::CodeAmbiguity;
 use super::CodeProjectionError;
 use super::CodeSelectionError;
-use super::{FulfillmentError, FulfillmentErrorCode, SelectionError};
-use super::{ObligationCause, BuiltinDerivedObligation};
-use super::{PredicateObligation, TraitObligation, Obligation};
+use super::{FulfillmentError, FulfillmentErrorCode};
+use super::{ObligationCause, PredicateObligation, Obligation};
 use super::project;
 use super::select::SelectionContext;
 use super::Unimplemented;
@@ -82,10 +79,6 @@ pub struct FulfillmentContext<'tcx> {
     // obligations (otherwise, it's easy to fail to walk to a
     // particular node-id).
     region_obligations: NodeMap<Vec<RegionObligation<'tcx>>>,
-
-    // A list of obligations that need to be deferred to
-    // a later time for them to be properly fulfilled.
-    deferred_obligations: Vec<DeferredObligation<'tcx>>,
 }
 
 #[derive(Clone)]
@@ -101,100 +94,12 @@ pub struct PendingPredicateObligation<'tcx> {
     pub stalled_on: Vec<Ty<'tcx>>,
 }
 
-/// An obligation which cannot be fulfilled in the context
-/// it was registered in, such as auto trait obligations on
-/// `impl Trait`, which require the concrete type to be
-/// available, only guaranteed after finishing type-checking.
-#[derive(Clone, Debug)]
-pub struct DeferredObligation<'tcx> {
-    pub predicate: ty::PolyTraitPredicate<'tcx>,
-    pub cause: ObligationCause<'tcx>
-}
-
-impl<'a, 'gcx, 'tcx> DeferredObligation<'tcx> {
-    /// If possible, create a `DeferredObligation` from
-    /// a trait predicate which had failed selection,
-    /// but could succeed later.
-    pub fn from_select_error(tcx: TyCtxt<'a, 'gcx, 'tcx>,
-                             obligation: &TraitObligation<'tcx>,
-                             selection_err: &SelectionError<'tcx>)
-                             -> Option<DeferredObligation<'tcx>> {
-        if let Unimplemented = *selection_err {
-            if DeferredObligation::must_defer(tcx, &obligation.predicate) {
-                return Some(DeferredObligation {
-                    predicate: obligation.predicate.clone(),
-                    cause: obligation.cause.clone()
-                });
-            }
-        }
-
-        None
-    }
-
-    /// Returns true if the given trait predicate can be
-    /// fulfilled at a later time.
-    pub fn must_defer(tcx: TyCtxt<'a, 'gcx, 'tcx>,
-                      predicate: &ty::PolyTraitPredicate<'tcx>)
-                      -> bool {
-        // Auto trait obligations on `impl Trait`.
-        if tcx.trait_has_default_impl(predicate.def_id()) {
-            let substs = predicate.skip_binder().trait_ref.substs;
-            if substs.types().count() == 1 && substs.regions().next().is_none() {
-                if let ty::TyAnon(..) = predicate.skip_binder().self_ty().sty {
-                    return true;
-                }
-            }
-        }
-
-        false
-    }
-
-    /// If possible, return the nested obligations required
-    /// to fulfill this obligation.
-    pub fn try_select(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>)
-                      -> Option<Vec<PredicateObligation<'tcx>>> {
-        if let ty::TyAnon(def_id, substs) = self.predicate.skip_binder().self_ty().sty {
-            let ty = if def_id.is_local() {
-                tcx.item_types.borrow().get(&def_id).cloned()
-            } else {
-                Some(tcx.item_type(def_id))
-            };
-            // We can resolve the `impl Trait` to its concrete type.
-            if let Some(concrete_ty) = ty.subst(tcx, substs) {
-                let predicate = ty::TraitRef {
-                    def_id: self.predicate.def_id(),
-                    substs: tcx.mk_substs_trait(concrete_ty, &[])
-                }.to_predicate();
-
-                let original_obligation = Obligation::new(self.cause.clone(),
-                                                          self.predicate.clone());
-                let cause = original_obligation.derived_cause(BuiltinDerivedObligation);
-                return Some(vec![Obligation::new(cause, predicate)]);
-            }
-        }
-
-        None
-    }
-
-    /// Return the `PredicateObligation` this was created from.
-    pub fn to_obligation(&self) -> PredicateObligation<'tcx> {
-        let predicate = ty::Predicate::Trait(self.predicate.clone());
-        Obligation::new(self.cause.clone(), predicate)
-    }
-
-    /// Return an error as if this obligation had failed.
-    pub fn to_error(&self) -> FulfillmentError<'tcx> {
-        FulfillmentError::new(self.to_obligation(), CodeSelectionError(Unimplemented))
-    }
-}
-
 impl<'a, 'gcx, 'tcx> FulfillmentContext<'tcx> {
     /// Creates a new fulfillment context.
     pub fn new() -> FulfillmentContext<'tcx> {
         FulfillmentContext {
             predicates: ObligationForest::new(),
             region_obligations: NodeMap(),
-            deferred_obligations: vec![],
         }
     }
 
@@ -294,16 +199,10 @@ impl<'a, 'gcx, 'tcx> FulfillmentContext<'tcx> {
     {
         self.select_where_possible(infcx)?;
 
-        // Fail all of the deferred obligations that haven't
-        // been otherwise removed from the context.
-        let deferred_errors = self.deferred_obligations.iter()
-                                  .map(|d| d.to_error());
-
         let errors: Vec<_> =
             self.predicates.to_errors(CodeAmbiguity)
                            .into_iter()
                            .map(|e| to_fulfillment_error(e))
-                           .chain(deferred_errors)
                            .collect();
         if errors.is_empty() {
             Ok(())
@@ -324,10 +223,6 @@ impl<'a, 'gcx, 'tcx> FulfillmentContext<'tcx> {
         self.predicates.pending_obligations()
     }
 
-    pub fn take_deferred_obligations(&mut self) -> Vec<DeferredObligation<'tcx>> {
-        mem::replace(&mut self.deferred_obligations, vec![])
-    }
-
     /// Attempts to select obligations using `selcx`. If `only_new_obligations` is true, then it
     /// only attempts to select obligations that haven't been seen before.
     fn select(&mut self, selcx: &mut SelectionContext<'a, 'gcx, 'tcx>)
@@ -343,7 +238,6 @@ impl<'a, 'gcx, 'tcx> FulfillmentContext<'tcx> {
             let outcome = self.predicates.process_obligations(&mut FulfillProcessor {
                 selcx: selcx,
                 region_obligations: &mut self.region_obligations,
-                deferred_obligations: &mut self.deferred_obligations
             });
             debug!("select: outcome={:?}", outcome);
 
@@ -378,7 +272,6 @@ impl<'a, 'gcx, 'tcx> FulfillmentContext<'tcx> {
 struct FulfillProcessor<'a, 'b: 'a, 'gcx: 'tcx, 'tcx: 'b> {
     selcx: &'a mut SelectionContext<'b, 'gcx, 'tcx>,
     region_obligations: &'a mut NodeMap<Vec<RegionObligation<'tcx>>>,
-    deferred_obligations: &'a mut Vec<DeferredObligation<'tcx>>
 }
 
 impl<'a, 'b, 'gcx, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'gcx, 'tcx> {
@@ -391,8 +284,7 @@ impl<'a, 'b, 'gcx, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'gcx,
     {
         process_predicate(self.selcx,
                           obligation,
-                          self.region_obligations,
-                          self.deferred_obligations)
+                          self.region_obligations)
             .map(|os| os.map(|os| os.into_iter().map(|o| PendingPredicateObligation {
                 obligation: o,
                 stalled_on: vec![]
@@ -432,8 +324,7 @@ fn trait_ref_type_vars<'a, 'gcx, 'tcx>(selcx: &mut SelectionContext<'a, 'gcx, 't
 fn process_predicate<'a, 'gcx, 'tcx>(
     selcx: &mut SelectionContext<'a, 'gcx, 'tcx>,
     pending_obligation: &mut PendingPredicateObligation<'tcx>,
-    region_obligations: &mut NodeMap<Vec<RegionObligation<'tcx>>>,
-    deferred_obligations: &mut Vec<DeferredObligation<'tcx>>)
+    region_obligations: &mut NodeMap<Vec<RegionObligation<'tcx>>>)
     -> Result<Option<Vec<PredicateObligation<'tcx>>>,
               FulfillmentErrorCode<'tcx>>
 {
@@ -502,21 +393,7 @@ fn process_predicate<'a, 'gcx, 'tcx>(
                     info!("selecting trait `{:?}` at depth {} yielded Err",
                           data, obligation.recursion_depth);
 
-                    let defer = DeferredObligation::from_select_error(selcx.tcx(),
-                                                                      &trait_obligation,
-                                                                      &selection_err);
-                    if let Some(deferred_obligation) = defer {
-                        if let Some(nested) = deferred_obligation.try_select(selcx.tcx()) {
-                            Ok(Some(nested))
-                        } else {
-                            // Pretend that the obligation succeeded,
-                            // but record it for later.
-                            deferred_obligations.push(deferred_obligation);
-                            Ok(Some(vec![]))
-                        }
-                    } else {
-                        Err(CodeSelectionError(selection_err))
-                    }
+                    Err(CodeSelectionError(selection_err))
                 }
             }
         }
@@ -714,12 +591,6 @@ impl<'a, 'gcx, 'tcx> GlobalFulfilledPredicates<'gcx> {
             // already has the required read edges, so we don't need
             // to add any more edges here.
             if data.is_global() {
-                // Don't cache predicates which were fulfilled
-                // by deferring them for later fulfillment.
-                if DeferredObligation::must_defer(tcx, data) {
-                    return;
-                }
-
                 if let Some(data) = tcx.lift_to_global(data) {
                     if self.set.insert(data.clone()) {
                         debug!("add_if_global: global predicate `{:?}` added", data);