]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc/middle/traits/coherence.rs
Implement default method inheritance.
[rust.git] / src / librustc / middle / traits / coherence.rs
index b0970457892bb6d846b975e57f9f30e64472e517..33a1e3816e348ce204d563190bab20ffcf494c90 100644 (file)
 
 //! See `README.md` for high-level documentation
 
-use super::Normalized;
-use super::SelectionContext;
-use super::ObligationCause;
-use super::PredicateObligation;
-use super::project;
+use super::{SelectionContext, Obligation, ObligationCause};
 use super::util;
 
 use middle::cstore::LOCAL_CRATE;
 use middle::def_id::DefId;
-use middle::subst::{Subst, Substs, TypeSpace};
+use middle::subst::TypeSpace;
 use middle::ty::{self, Ty, TyCtxt};
 use middle::infer::{self, InferCtxt, TypeOrigin};
-use syntax::codemap::{DUMMY_SP, Span};
+use syntax::codemap::DUMMY_SP;
 
 #[derive(Copy, Clone)]
 struct InferIsLocal(bool);
 
-/// If there are types that satisfy both impls, returns a `TraitRef`
-/// with those types substituted (by updating the given `infcx`)
+/// If there are types that satisfy both impls, returns a suitably-freshened
+/// `ImplHeader` with those types substituted
 pub fn overlapping_impls<'cx, 'tcx>(infcx: &InferCtxt<'cx, 'tcx>,
                                     impl1_def_id: DefId,
                                     impl2_def_id: DefId)
-                                    -> Option<ty::TraitRef<'tcx>>
+                                    -> Option<ty::ImplHeader<'tcx>>
 {
     debug!("impl_can_satisfy(\
            impl1_def_id={:?}, \
@@ -45,34 +41,28 @@ pub fn overlapping_impls<'cx, 'tcx>(infcx: &InferCtxt<'cx, 'tcx>,
 }
 
 /// Can both impl `a` and impl `b` be satisfied by a common type (including
-/// `where` clauses)? If so, returns a `TraitRef` that unifies the two impls.
+/// `where` clauses)? If so, returns an `ImplHeader` that unifies the two impls.
 fn overlap<'cx, 'tcx>(selcx: &mut SelectionContext<'cx, 'tcx>,
                       a_def_id: DefId,
                       b_def_id: DefId)
-                      -> Option<ty::TraitRef<'tcx>>
+                      -> Option<ty::ImplHeader<'tcx>>
 {
     debug!("overlap(a_def_id={:?}, b_def_id={:?})",
            a_def_id,
            b_def_id);
 
-    let (a_trait_ref, a_obligations) = impl_trait_ref_and_oblig(selcx,
-                                                                a_def_id,
-                                                                util::fresh_type_vars_for_impl);
+    let a_impl_header = ty::ImplHeader::with_fresh_ty_vars(selcx, a_def_id);
+    let b_impl_header = ty::ImplHeader::with_fresh_ty_vars(selcx, b_def_id);
 
-    let (b_trait_ref, b_obligations) = impl_trait_ref_and_oblig(selcx,
-                                                                b_def_id,
-                                                                util::fresh_type_vars_for_impl);
-
-    debug!("overlap: a_trait_ref={:?} a_obligations={:?}", a_trait_ref, a_obligations);
-
-    debug!("overlap: b_trait_ref={:?} b_obligations={:?}", b_trait_ref, b_obligations);
+    debug!("overlap: a_impl_header={:?}", a_impl_header);
+    debug!("overlap: b_impl_header={:?}", b_impl_header);
 
     // Do `a` and `b` unify? If not, no overlap.
-    if let Err(_) = infer::mk_eq_trait_refs(selcx.infcx(),
-                                            true,
-                                            TypeOrigin::Misc(DUMMY_SP),
-                                            a_trait_ref,
-                                            b_trait_ref) {
+    if let Err(_) = infer::mk_eq_impl_headers(selcx.infcx(),
+                                              true,
+                                              TypeOrigin::Misc(DUMMY_SP),
+                                              &a_impl_header,
+                                              &b_impl_header) {
         return None;
     }
 
@@ -81,9 +71,13 @@ fn overlap<'cx, 'tcx>(selcx: &mut SelectionContext<'cx, 'tcx>,
     // Are any of the obligations unsatisfiable? If so, no overlap.
     let infcx = selcx.infcx();
     let opt_failing_obligation =
-        a_obligations.iter()
-                     .chain(&b_obligations)
-                     .map(|o| infcx.resolve_type_vars_if_possible(o))
+        a_impl_header.predicates
+                     .iter()
+                     .chain(&b_impl_header.predicates)
+                     .map(|p| infcx.resolve_type_vars_if_possible(p))
+                     .map(|p| Obligation { cause: ObligationCause::dummy(),
+                                           recursion_depth: 0,
+                                           predicate: p })
                      .find(|o| !selcx.evaluate_obligation(o));
 
     if let Some(failing_obligation) = opt_failing_obligation {
@@ -91,7 +85,7 @@ fn overlap<'cx, 'tcx>(selcx: &mut SelectionContext<'cx, 'tcx>,
         return None
     }
 
-    Some(selcx.infcx().resolve_type_vars_if_possible(&a_trait_ref))
+    Some(selcx.infcx().resolve_type_vars_if_possible(&a_impl_header))
 }
 
 pub fn trait_ref_is_knowable<'tcx>(tcx: &TyCtxt<'tcx>, trait_ref: &ty::TraitRef<'tcx>) -> bool
@@ -125,44 +119,6 @@ pub fn trait_ref_is_knowable<'tcx>(tcx: &TyCtxt<'tcx>, trait_ref: &ty::TraitRef<
     orphan_check_trait_ref(tcx, trait_ref, InferIsLocal(true)).is_err()
 }
 
-type SubstsFn = for<'a,'tcx> fn(infcx: &InferCtxt<'a, 'tcx>,
-                                span: Span,
-                                impl_def_id: DefId)
-                                -> Substs<'tcx>;
-
-/// Instantiate fresh variables for all bound parameters of the impl
-/// and return the impl trait ref with those variables substituted.
-fn impl_trait_ref_and_oblig<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
-                                     impl_def_id: DefId,
-                                     substs_fn: SubstsFn)
-                                     -> (ty::TraitRef<'tcx>,
-                                         Vec<PredicateObligation<'tcx>>)
-{
-    let impl_substs =
-        &substs_fn(selcx.infcx(), DUMMY_SP, impl_def_id);
-    let impl_trait_ref =
-        selcx.tcx().impl_trait_ref(impl_def_id).unwrap();
-    let impl_trait_ref =
-        impl_trait_ref.subst(selcx.tcx(), impl_substs);
-    let Normalized { value: impl_trait_ref, obligations: normalization_obligations1 } =
-        project::normalize(selcx, ObligationCause::dummy(), &impl_trait_ref);
-
-    let predicates = selcx.tcx().lookup_predicates(impl_def_id);
-    let predicates = predicates.instantiate(selcx.tcx(), impl_substs);
-    let Normalized { value: predicates, obligations: normalization_obligations2 } =
-        project::normalize(selcx, ObligationCause::dummy(), &predicates);
-    let impl_obligations =
-        util::predicates_for_generics(ObligationCause::dummy(), 0, &predicates);
-
-    let impl_obligations: Vec<_> =
-        impl_obligations.into_iter()
-        .chain(normalization_obligations1)
-        .chain(normalization_obligations2)
-        .collect();
-
-    (impl_trait_ref, impl_obligations)
-}
-
 pub enum OrphanCheckErr<'tcx> {
     NoLocalInputType,
     UncoveredTy(Ty<'tcx>),
@@ -301,7 +257,8 @@ fn ty_is_local_constructor<'tcx>(tcx: &TyCtxt<'tcx>,
         ty::TyUint(..) |
         ty::TyFloat(..) |
         ty::TyStr |
-        ty::TyBareFn(..) |
+        ty::TyFnDef(..) |
+        ty::TyFnPtr(_) |
         ty::TyArray(..) |
         ty::TySlice(..) |
         ty::TyRawPtr(..) |